chrome事件循环的自问自答

chrome,事件,循环,自问自答 · 浏览次数 : 235

小编点评

1. **宏任务**是事件循环的核心概念,它包含对DOM的操作,并被浏览器在事件循环中执行。 2. **微任务**是事件循环中更小的单元,它们通常包含对DOM的操作,但它们不是事件循环中执行的。 3. **dom渲染**是事件循环的一部分,因为它涉及对DOM的操作。如果一个渲染帧的时间远大于事件循环周期,则可能不执行相应的DOM渲染操作。 4. **requestAnimationFrame**的回调函数是事件循环的一部分,因为它会在浏览器在下一帧渲染之前执行。 5. **requestIdleCallback**的回调是事件循环的一部分,因为它是在浏览器空闲时期被调用的。 6. **事件循环图例**展示了多个事件循环执行的流程,包括宏任务、微任务、dom渲染等操作。

正文

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);

image

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内执行;

image

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>

image

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

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

image

6. 事件循环图例

image

与chrome事件循环的自问自答相似的内容:

chrome事件循环的自问自答

# chrome事件循环的自问自答 ## 目录 - [1. 宏任务有哪些?](#1-宏任务有哪些) - [2. 微任务有哪些?](#2-微任务有哪些) - [3. dom渲染是事件循环的一部分么?](#3-dom渲染是事件循环的一部分么) - [4. requestAnimationFrame的回调

基于Chrome扩展的浏览器可信事件与网页离线PDF导出

基于Chrome扩展的浏览器可信事件与网页离线PDF导出 Chrome扩展是一种可以在浏览器中添加新功能和修改浏览器行为的软件程序,我们可以基于Manifest规范的API实现对于浏览器和Web页面在一定程度上的修改,例如广告拦截、代理控制等。Chrome DevTools Protocol则是Ch

使用Chrome 开发者工具提取对应的字符串

最近在查看一个API的数据,效果很好,但是里面只有一部分我想要的内容 如果是简单一点的可以直接获取 如下比如我想要提取返回的代码中关键的字符串:"video": "这里的内容" // 定义一个正则表达式来匹配 '"video": "链接"' 格式的字符串 var regex = /"video":\

从油猴脚本管理器的角度审视Chrome扩展

从油猴脚本管理器的角度审视Chrome扩展 在之前一段时间,我需要借助Chrome扩展来完成一个需求,当时还在使用油猴脚本与浏览器扩展之间调研了一波,而此时恰好我又有一些做的还可以的油猴脚本 TKScript ,相对会比较熟悉脚本管理器的能力,预估是不太能完成需求的,所以趁着这个机会,我又学习了一波

​Chrome插件:Postman Interceptor 调试的终极利器

今天给大家介绍一款非常实用的工具——Postman Interceptor。 这个工具可以捕捉任何网站的请求,并将其发送到Postman客户端。 对于经常和API打交道的程序员来说,Postman Interceptor真的是神器级别的存在。 下面就让我详细说说这个插件怎么用,有哪些优势,以及我的一

【现代 CSS】标准滚动条控制规范 scrollbar-color 和 scrollbar-width

Chrome 在 121 版本开始,原生支持了两个滚动条样式相关的样式 scrollbar-color 和 scrollbar-width。 要知道,在此前,虽然有 ::-webkit-scrollbar 规范可以控制滚动条,可是,::-webkit-scrollbar 是非标准特性,在 MDN 文

[转帖]chrome 查看已经保存的密码

方法/步骤 1 点击浏览器工具栏右上角的三个竖点的菜单图标 2 在弹出来的菜单列表中点击打开“设置” 3 在设置界面点击左侧的“自动填充” 4 接着在右侧找到“已保存的密码”,在其下方找到需要查看的网站密码 5 点击密码后面的眼睛的图标 6 在弹出的窗口中输入电脑的登录密码,点击下方的“确定”即可查

[转帖]Chrome, Firefox(火狐), Edge 官方离线安装包下载

https://zhuanlan.zhihu.com/p/183834818 Google Chrome 离线安装包 正式版: https://www.google.cn/chrome/?hl=zh-CN&standalone=1 测试版: https://www.google.cn/intl/zh

[转帖]Chrome 各版本下载集合

https://www.cnblogs.com/itelite/p/3798226.html Windows平台: Chrome 在线安装包: 最新稳定版(Stable Channel)Chrome在线安装: 【点击这里】 最新测试版(Beta Channel)Chrome在线安装: 【点击这里】

Chrome浏览器不同版本兼容性的验证方法

Chrome浏览器不同版本兼容性的验证方法 背景 上周客户现场有出现使用国产信创设备上面的奇安信浏览器出现兼容性的问题. 开发认为是测试不全面导致. 认为测试应该必须测试过特定浏览器才可以进行说明. 最开始国产设备上面仅能够支持firefox52.3ESR的版本 当时在进行银河麒麟和UOS的兼容适配