浅谈javascript事件环微任务和宏任务队列原理


Posted in Javascript onSeptember 12, 2020

JS 事件环

JS 程序的运行是离不开事件环机制的,这个机制保证在发生某些事情的时候我们有机会执行一个我们事先预定好的函数,事情发生的时候 JS 会将相应的函数入栈执行然后出栈,但是关于事件环我们还有一些未知的东西,例如,setTimeout 我们习惯称他为定时器,但是可能很多人没有意识到,这个东西和我们常用的一些事件没什么不同,只不过我们通常所说的事件大多需要用户触发,而 setTimeout 不用用户自己触发,而是指定时间之后触发;那么问题来了,如果我们将时间设置为 0 会发生什么?会立即执行么?

setTimeout、DOM或者 HTTP请求这部分其实并不在 v8 引擎中,这些属于 web API,javascript 是一个单线程的语言,也就意味着一次只能做一件事情,这个事实从未改变

执行原理

JS 中所有的方法都会被推入栈中执行,执行完成被弹出,在遇到异步代码的时候,例如 setTimeout MutationObserver Promise 异步的部分会由其他掌管 webAPI 的地方执行,等异步有结果之后,回调函数会进入相应的队列,Promise MutationObserver 回调进入微任务队列,setTimeout setInterval requestAnimationFrame 进入宏任务队列。等待主线程的执行栈空了,微任务队列立刻被推入栈中执行,执行完毕开始执行宏任务队列

浅谈javascript事件环微任务和宏任务队列原理

一个经典的例子

html

<div class="outer">
 <div class="inner"></div>
</div>

js

// Let's get hold of those elements
var outer = document.querySelector('.outer');
var inner = document.querySelector('.inner');

// Let's listen for attribute changes on the
// outer element
new MutationObserver(function () {
 console.log('mutate');
}).observe(outer, {
 attributes: true,
});

// Here's a click listener…
function onClick() {
 console.log('click');

 setTimeout(function () {
  console.log('timeout');
 }, 0);

 Promise.resolve().then(function () {
  console.log('promise');
 });

 outer.setAttribute('data-random', Math.random());
}

// …which we'll attach to both elements
inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);

以上代码在,手动点击 inner 元素的时候会有如下输出

click
promise
mutate
click
promise
mutate
timeout
timeout

截止 2020年8月份 chrome edge opera firefox 的结果是统一的,但是在此之前的版本可能会有不同的输出。

一个奇怪的现象

上述代码我们不使用手动触发点击,而是使用 inner.click() 触发点击,其结果会有很大的不同

click
click
promise
mutate
promise
timeout
timeout

造成以上巨大差异的原因是,手动点击,不是通过函数进入执行栈的方式触发点击事件的回调,所以inner 的回调执行完了主线程中的执行栈就是空的可以直接执行队列中任务,然后事件冒泡导致的回调函数才被推入栈运行;而 click 方法的点击则是通过将 click 推入栈中执行来达到的,inner 的点击回调执行完了之后 click 方法并没有被弹出栈,而是直接执行冒泡的下一个回调,由于下一个回调有一个重复的 属性设置 这是不会重复触发 MutationObserver的所以 mutate 的输出只会有一个。等所有的冒泡回调被执行完毕 click 函数才会被弹出栈。

最后注意,浏览器会尽量预先执行较为敏感的操作。

以上就是浅谈javascript事件环微任务和宏任务队列原理的详细内容,更多关于JavaScript 事件环的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
My Desktop :) 桌面式代码
Dec 29 Javascript
JavaScript 原型链学习总结
Oct 29 Javascript
基于js与flash实现的网站flv视频播放插件代码
Oct 14 Javascript
JS数组的常见用法实例
Feb 10 Javascript
JavaScript跨浏览器获取页面中相同class节点的方法
Mar 03 Javascript
JavaScript获取URL汇总
Jun 08 Javascript
JavaScript让Textarea支持tab按键的方法
Jun 26 Javascript
jquery+css实现绚丽的横向二级下拉菜单-附源码下载
Aug 23 Javascript
jQuery选择器用法实例详解
Dec 17 Javascript
详解vue-router 初始化时做了什么
Jun 11 Javascript
React组件设计模式之组合组件应用实例分析
Apr 29 Javascript
详解node.js创建一个web服务器(Server)的详细步骤
Jan 15 Javascript
返回上一个url并刷新界面的js代码
Sep 12 #Javascript
Vue和React有哪些区别
Sep 12 #Javascript
浅谈vue项目利用Hbuilder打包成APP流程,以及遇到的坑
Sep 12 #Javascript
解决vue项目 build之后资源文件找不到的问题
Sep 12 #Javascript
vue项目打包为APP,静态资源正常显示,但API请求不到数据的操作
Sep 12 #Javascript
vue v-on:click传递动态参数的步骤
Sep 11 #Javascript
vue Cli 环境删除与重装教程 - 版本文档
Sep 11 #Javascript
You might like
PHP define函数的使用说明
2008/08/27 PHP
php实现监控varnish缓存服务器的状态
2014/12/30 PHP
php版微信公众平台回复中文出现乱码问题的解决方法
2016/09/22 PHP
PHP+mysql+ajax轻量级聊天室实现方法详解
2016/10/17 PHP
自制PHP框架之路由与控制器
2017/05/07 PHP
拖拉表格的JS函数
2008/11/20 Javascript
JavaScript QueryString解析类代码
2010/01/17 Javascript
SOSO地图API使用(一)在地图上画圆实现思路与代码
2013/01/15 Javascript
jQuery探测位置的提示弹窗(toolTip box)详细解析
2013/11/14 Javascript
jquery删除ID为sNews的tr元素的内容
2014/04/10 Javascript
JavaScript获取文本框内选中文本的方法
2015/02/20 Javascript
使用jquery清空、复位整个输入域
2015/04/02 Javascript
如何使用JS在HTML中自定义字符串格式化
2017/07/20 Javascript
在原生不支持的旧环境中添加兼容的Object.keys实现方法
2017/09/11 Javascript
JavaScript的词法结构精华篇
2018/10/17 Javascript
微信小程序在ios下Echarts图表不能滑动的问题解决
2019/07/10 Javascript
对layui初始化列表的CheckBox属性详解
2019/09/13 Javascript
使用p5.js实现动态GIF图片临摹重现
2019/10/23 Javascript
详解Vue Cli浏览器兼容性实践
2020/06/08 Javascript
python获取mp3文件信息的方法
2015/06/15 Python
举例讲解Python中的死锁、可重入锁和互斥锁
2015/11/05 Python
Python实现完整的事务操作示例
2017/06/20 Python
解决已经安装requests,却依然提示No module named requests问题
2018/05/18 Python
python判断正负数方式
2020/06/03 Python
Python判断远程服务器上Excel文件是否被人打开的方法
2020/07/13 Python
python 6行代码制作月历生成器
2020/09/18 Python
Python 利用flask搭建一个共享服务器的步骤
2020/12/05 Python
CSS3实现菜单悬停效果
2020/11/17 HTML / CSS
美国现代家具和家居商店:Apt2B
2016/08/29 全球购物
怀旧收藏品和经典纪念品:Betty’s Attic
2018/08/29 全球购物
麦当劳印度网上订餐:McDelivery
2020/03/16 全球购物
澳大利亚在线床零售商:Bedworks
2020/09/01 全球购物
群众对十八届四中全会的期盼
2014/10/17 职场文书
刑事和解协议书范本
2014/11/19 职场文书
小学班主任个人总结
2015/03/03 职场文书
2015年学校医务室工作总结
2015/07/20 职场文书