chrome事件循环的自问自答
chrome事件循环的自问自答
目录
- 1. 宏任务有哪些?
- 2. 微任务有哪些?
- 3. dom渲染是事件循环的一部分么?
- 4. requestAnimationFrame的回调是宏任务还是微任务?
- 5. requestIdleCallback的回调是宏任务还是微任务?
- 6. 事件循环图例
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事件循环的自问自答的更多相关文章
- nodejs的事件循环1
JavaScript的学习零散而庞杂,因此很多时候我们学到了一些东西,但是却没办法感受到自己的进步,甚至过了不久,就把学到的东西给忘了.为了解决自己的这个困扰,在学习的过程中,我一直试图在寻找一条核心 ...
- JavaScript单线程和浏览器事件循环简述
JavaScript单线程 在上篇博客<Promise的前世今生和妙用技巧>的开篇中,我们曾简述了JavaScript的单线程机制和浏览器的事件模型.应很多网友的回复,在这篇文章中将继续展 ...
- js事件循环
之前有看过一些事件循环的博客,不过一阵子没看就发现自己忘光了,所以决定来自己写一个博客总结下! 首先,我们来解释下事件循环是个什么东西: 就我们所知,浏览器的js是单线程的,也就是说,在同一时刻,最多 ...
- 深入理解 JavaScript 事件循环(二)— task and microtask
引言 microtask 这一名词是 JS 中比较新的概念,几乎所有人都是在学习 ES6 的 Promise 时才接触这一新概念,我也不例外.当我刚开始学习 Promise 的时候,对其中回调函数的执 ...
- 浏览器与Node的事件循环(Event Loop)有何区别?
前言 本文我们将会介绍 JS 实现异步的原理,并且了解了在浏览器和 Node 中 Event Loop 其实是不相同的. 一.线程与进程 1. 概念 我们经常说 JS 是单线程执行的,指的是一个进程里 ...
- 详解JavaScript中的Event Loop(事件循环)机制
前言 我们都知道,javascript从诞生之日起就是一门单线程的非阻塞的脚本语言.这是由其最初的用途来决定的:与浏览器交互. 单线程意味着,javascript代码在执行的任何时候,都只有一个主线程 ...
- [译] 深入理解 JavaScript 事件循环(二)— task and microtask
引言 microtask 这一名词是 JS 中比较新的概念,几乎所有人都是在学习 ES6 的 Promise 时才接触这一新概念,我也不例外.当我刚开始学习 Promise 的时候,对其中回调函数的执 ...
- 理解js事件循环(event loop)
队列:先进先出 栈:后进先出 javascript的Event Loop 和 Node.js的Event Loop 区别: js(运行在浏览器),有主线程.异步任务队列的概念: node.js使用li ...
- css自问自答(二)
css自问自答(二) 7.掌握定位的一些属性 position 和 display 属性,以及如何浮动(float)和清除(clear)元素,z-index属性 三个属性控制: position 属性 ...
- c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)
c#封装DBHelper类 public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...
随机推荐
- Go语言实战: 即时通信系统(未完)
使用Go语言构建一个即时通信系统,旨在锻炼Go语言编程能力 该通信系统至少能够允许用户能够在客户端进行公聊,即所发消息能被所有用户看到,也可发起私聊(即两个用户之间私密通信).同时,用户能够看到当前有 ...
- 测试环境治理之MYSQL索引优化篇
作者:京东物流 李光新 1 治理背景 测试环境这个话题对于开发和测试同学一定不陌生,大家几乎每天都会接触.但是说到对测试环境的印象,却鲜有好评: •环境不稳定,测试五分钟,排查两小时 •基础建设不全, ...
- Android刷机日记
0x01 工具准备(镜像之类的注意下载的版本要与手机一致) 1)SDK工具 https://developer.android.com/studio/releases/platform-tools?h ...
- MAPPO学习笔记(2) —— 从MAPPO论文入手
在有了上一节一些有关PPO算法的概念作为基础后,我们就可以正式开始对于MAPPO这一算法的学习. 那么,既然要学习一个算法,就不得不去阅读提出这一算法的论文.那么本篇博客将从MAPPO的论文出发,对M ...
- day07-优惠券秒杀03
功能03-优惠券秒杀03 4.功能03-优惠券秒杀 4.6Redisson的分布式锁 Redis分布式锁-Redisson+RLock可重入锁实现篇 4.6.1基于setnx实现的分布式锁问题 我们在 ...
- GaussDB(DWS)网络流控与管控效果
摘要:本文主要介绍GaussDB(DWS)网络流控能力,并对其管控效果进行验证. 本文分享自华为云社区<GaussDB(DWS)网络流控与管控效果>,作者:门前一棵葡萄树. 上一篇博文Ga ...
- 2020-12-29:mysql中,innodb表里,某一条数据删除了之后,这条数据会被真实的擦掉吗,还是删除了关系?
福哥答案2020-12-29:[答案来自此链接,答案相当详细:](https://www.zhihu.com/question/436957843)面试的时候受 <MySQL技术内幕 InnoD ...
- 2021-05-12:给定一个数组arr,只能对arr中的一个子数组排序, 但是想让arr整体都有序。返回满足这一设定的子数组中,最短的是多长?
2021-05-12:给定一个数组arr,只能对arr中的一个子数组排序, 但是想让arr整体都有序.返回满足这一设定的子数组中,最短的是多长? 福大大 答案2021-05-12: 从左往右遍历,缓存 ...
- Selenium - 浏览器配置(1) - 忽略证书错误提示
Selenium - 浏览器配置 忽略证书错误提示 有时候我们访问一些地址,会提示证书私密连接告警信息如下: 如果我们每次要点击高级来忽略私密连接,那就很麻烦: 在谷歌浏览器可以增加忽略证书错误问题, ...
- Django4全栈进阶之路21 项目实战(三种方式开发部门管理):方式二:CBV+Django内置类(ListView, CreateView, UpdateView, DeleteView, DetailView)
在 Django 中,视图(View)是处理请求并返回响应的主要机制.Django 中有许多视图类可用于处理常见的 CRUD(Create.Read.Update.Delete)操作以及其他类型的请求 ...