chrome事件循环的自问自答

目录

1. 宏任务有哪些?

  • 事件回调 (js调用的 click box.click()
  • XHR或网络请求回调
  • 定时器的回调
  • I/O回调
  • history相关回调
  • MessageChannel的message回调

在合适时机,这些宏任务会被推入宏任务队列;每一次事件循环会从宏任务队列中取一个任务执行。

history.back回调:

<button id='box'>forward</button>
<button id='box2'>back</button> <script>
var box = document.getElementById('box');
var box2 = document.getElementById('box2');
box.addEventListener('click',()=>{
history.pushState('state',null,'?page=1');
}) window.addEventListener('popstate',function (ev) {
console.log('popstate');
})
box2.addEventListener('click',()=>{
history.back();
setTimeout(()=>{
console.log('timeout');
})
})
</script>

MessageChannel的message回调

<button id='btn'>btn</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = function () {
var channel = new MessageChannel();
channel.port1.onmessage = function onmessage1 (){
console.log('postMessage')
Promise.resolve().then(function promise1 (){
console.log('promise')
})
};
setTimeout(function setTimeout2(){
console.log('setTimeout')
}, 0)
channel.port2.postMessage(0);
};
</script>

I/O回调

<input type="file" id="input" multiple>
<script>
input.addEventListener('change', function () {
var file = input.files[0]
var reader = new FileReader()
reader.onload = function (ev) {
console.log(reader.result);
}
reader.readAsArrayBuffer(file)
})
</script>

2. 微任务有哪些?

MutationObserver的回调、Promise的then catch finally回调、queueMicrotask.

在合适时机,这些微任务会被推入微任务队列;每一次事件循环会从微任务队列中取所有任务并执行。

Promise和queueMicrotask不支持IE, MutationObserver支持IE11;

MutationObserver例子:

下面的代码中box.textContent = 1的位置不同,代码的执行顺序就不同以验证MutationObserver为微任务。

<div id='box'>0</div>
<script>
const box = document.getElementById('box');
const mo = new MutationObserver(function (mutations) {
console.log('mutations')
})
mo.observe(box, {
childList: true
})
box.onclick = function () {
// box.textContent = 1;
Promise.resolve().then(()=>{
console.log(333)
})
box.textContent = 1;
};
</script>

以下是使用`queueMicrotask`方法手动添加微任务的例子,可以不会对更高优先级的代码运行造成干扰。

<div id='box'>0</div>
<script>
const box = document.getElementById('box');
box.onclick = function () {
queueMicrotask(()=>{
console.log(121212)
})
console.log(333)
};
</script>

3. dom渲染是事件循环的一部分么?

从规范的角度来看,DOM渲染是事件循环的一部分,可以将其视为一种渲染任务。

如果宏任务或者微任务中发生了dom修改,因为一个渲染帧的时间可能远大于事件循环周期,所以不一定在本次事件循环会执行渲染任务。

<div id='box'>0</div>
<script>
const box = document.getElementById('box');
box.onclick = function () {
setTimeout(function setTimeout17 () {
box.textContent = 1;
}, 0)
setTimeout(function setTimeout18 () {
box.textContent = 2;
}, 0)
};
</script>

下图是上面的代码的执行流程,两个setTimeout的回调执行代表两次事件循环,在其后面出现了一个新的Task,仅执行了一次布局(layout)和绘制(paint);

4. requestAnimationFrame的回调是宏任务还是微任务?

requestAnimationFrame的回调函数会在浏览器在下一帧渲染之前执行, 既不是宏任务,也不是微任务, 从规范上看是事件循环的一部分,从下图可以看到一个task下包含了requestAnimationFrame,layout paint, 可将其归类于渲染任务的一个可选步骤。

<div id='box'>0</div>
<script>
const box = document.getElementById('box');
box.onclick = function () {
setTimeout(function setTimeout17 () {
box.textContent = 1;
requestAnimationFrame(()=>{
console.log(111)
Promise.resolve().then(()=>{
console.log(333)
})
})
}, 0)
setTimeout(function setTimeout18 () {
box.textContent = 2;
requestAnimationFrame(()=>{
console.log(222)
})
}, 0)
};
</script>

上述代码中添加了两个requestAnimationFrame,可以看到两者在一个Task内顺序执行;并且回调中的微任务也在这个Task内执行;

5. requestIdleCallback的回调是宏任务还是微任务?

requestIdleCallback是事件循环的一部分,从图中可以看到,requestIdleCallback的回调是一个特殊的任务,这个函数的回调会在浏览器空闲时期被调用,所以不是每次循环都会执行该任务。

<button id='btn'>btn</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = function () {
requestIdleCallback(function () {
btn.innerHTML = "sdfsdfs"
setTimeout(()=>{
console.log(3)
},0)
Promise.resolve().then(()=>{
console.log(4)
})
})
};
</script>

该任务的优先级比较低,多个平行声明的requestIdleCallback会拆开成单一的task, 两个连续task之间甚至会被内部的setTimeout插足。

for (let i = 0; i < 10; i++) {
requestIdleCallback(() => {
console.log('idle', Date.now() - a)
setTimeout(()=>{
console.log(12121)
})
})
}

6. 事件循环图例

chrome事件循环的自问自答的更多相关文章

  1. nodejs的事件循环1

    JavaScript的学习零散而庞杂,因此很多时候我们学到了一些东西,但是却没办法感受到自己的进步,甚至过了不久,就把学到的东西给忘了.为了解决自己的这个困扰,在学习的过程中,我一直试图在寻找一条核心 ...

  2. JavaScript单线程和浏览器事件循环简述

    JavaScript单线程 在上篇博客<Promise的前世今生和妙用技巧>的开篇中,我们曾简述了JavaScript的单线程机制和浏览器的事件模型.应很多网友的回复,在这篇文章中将继续展 ...

  3. js事件循环

    之前有看过一些事件循环的博客,不过一阵子没看就发现自己忘光了,所以决定来自己写一个博客总结下! 首先,我们来解释下事件循环是个什么东西: 就我们所知,浏览器的js是单线程的,也就是说,在同一时刻,最多 ...

  4. 深入理解 JavaScript 事件循环(二)— task and microtask

    引言 microtask 这一名词是 JS 中比较新的概念,几乎所有人都是在学习 ES6 的 Promise 时才接触这一新概念,我也不例外.当我刚开始学习 Promise 的时候,对其中回调函数的执 ...

  5. 浏览器与Node的事件循环(Event Loop)有何区别?

    前言 本文我们将会介绍 JS 实现异步的原理,并且了解了在浏览器和 Node 中 Event Loop 其实是不相同的. 一.线程与进程 1. 概念 我们经常说 JS 是单线程执行的,指的是一个进程里 ...

  6. 详解JavaScript中的Event Loop(事件循环)机制

    前言 我们都知道,javascript从诞生之日起就是一门单线程的非阻塞的脚本语言.这是由其最初的用途来决定的:与浏览器交互. 单线程意味着,javascript代码在执行的任何时候,都只有一个主线程 ...

  7. [译] 深入理解 JavaScript 事件循环(二)— task and microtask

    引言 microtask 这一名词是 JS 中比较新的概念,几乎所有人都是在学习 ES6 的 Promise 时才接触这一新概念,我也不例外.当我刚开始学习 Promise 的时候,对其中回调函数的执 ...

  8. 理解js事件循环(event loop)

    队列:先进先出 栈:后进先出 javascript的Event Loop 和 Node.js的Event Loop 区别: js(运行在浏览器),有主线程.异步任务队列的概念: node.js使用li ...

  9. css自问自答(二)

    css自问自答(二) 7.掌握定位的一些属性 position 和 display 属性,以及如何浮动(float)和清除(clear)元素,z-index属性 三个属性控制: position 属性 ...

  10. c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)

    c#封装DBHelper类   public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...

随机推荐

  1. Kubuesphere部署Ruoyi(二):部署kubesphere

    先决条件: 更换DNS 更换apt的镜像源 Ubuntu下永久性修改DNS vi /etc/systemd/resolved.conf DNS字段取消注释,并修改DNS为223.5.5.5 223.5 ...

  2. 使用select需要注意的细节

    使用select需要注意的细节 在学校的时候就使用过select,但是在项目中使用的时候却犯了个错误. select如何使用就不进行总结了,网上教程太多,以下是项目中我写的一小段代码,便于总结. in ...

  3. [Pytorch框架] 2.5 循环神经网络

    文章目录 2.5 循环神经网络 2.5.1 RNN简介 RNN的起因 为什么需要RNN RNN都能做什么 2.5.2 RNN的网络结构及原理 RNN LSTM GRU 2.5.3 循环网络的向后传播( ...

  4. [OpenCV-Python] 19 Canny 边缘检测

    文章目录 OpenCV-Python:IV OpenCV中的图像处理 19 Canny 边缘检测 19.1 原理 19.1.1 噪声去除 19.1.2 计算图像梯度 19.1.3 非极大值抑制 19. ...

  5. 用Aspose-Java免费实现 PDF、Word、Excel、Word互相转换并将转换过得文件上传OSS,返回转换后的文件路径

    嘿嘿嘿.嘿嘿,俺又回来了! github代码地址 https://github.com/Tom-shushu/work-study 接口文档有道云 https://note.youdao.com/s/ ...

  6. 文心一言 VS chatgpt (5)-- 算法导论2.2 3~4题

    三.再次考虑线性查找问题(参见练习 2.1-3).假定要查找的元素等可能地为数组中的任意元素,平均需要检查输入序列的多少元素?最坏情况又如何呢?用0记号给出线性查找的平均情况和最坏情况运行时间.证明你 ...

  7. 2023-04-04:使用 Golang 和 ffmpeg-go 库实现 demuxing_decoding.c,轻松掌握音视频分离解码技巧。

    2023-04-04:使用 Golang 和 ffmpeg-go 库实现 demuxing_decoding.c,轻松掌握音视频分离解码技巧. 答案2023-04-05: 使用github/moonf ...

  8. 2022-11-29:查找重复的电子邮箱。以下数据中a@b.com是重复的,请写出sql语句。 DROP TABLE IF EXISTS person; CREATE TABLE person (

    2022-11-29:查找重复的电子邮箱.以下数据中a@b.com是重复的,请写出sql语句. DROP TABLE IF EXISTS person; CREATE TABLE person ( i ...

  9. 2022-06-13:golang中,[]byte和结构体如何相互转换?

    2022-06-13:golang中,[]byte和结构体如何相互转换? 答案2022-06-13: []byte和结构体的转换的应用场景是数据解析. 代码里有两种方法,一种是内存不共用,另一种是内存 ...

  10. Selenium - 元素等待(2) - 显式等待/EC等待

    Selenium - 元素等待 显式等待 显式等待是一种灵活的等待方式,需要声明等待的结束条件,当满足条件时会自动结束等待: 需要引入WebDriverWait包以及exception_conditi ...