浅谈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 相关文章推荐
遍历DOM对象内的元素属性示例代码
Feb 08 Javascript
Js冒泡事件详解及阻止示例
Mar 21 Javascript
jquery实现通用版鼠标经过淡入淡出效果
Jun 15 Javascript
JavaScript实现向setTimeout执行代码传递参数的方法
Apr 16 Javascript
浅谈bootstrap源码分析之scrollspy(滚动侦听)
Jun 06 Javascript
多种jQuery绑定事件的实现方式
Jun 13 Javascript
js输出数据精确到小数点后n位代码
Jul 02 Javascript
整理一下常见的IE错误
Nov 18 Javascript
Angular使用ng-messages与PHP进行表单数据验证
Dec 28 Javascript
Angular HMR(热模块替换)功能实现方法
Apr 04 Javascript
vue select选择框数据变化监听方法
Aug 24 Javascript
js仿淘宝放大镜效果
Dec 28 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获取文件绝对路径的代码(上一级目录)
2011/05/29 PHP
PHP转换IP地址到真实地址的方法详解
2013/06/09 PHP
codeigniter教程之多文件上传使用示例
2014/02/11 PHP
php使用GeoIP库实例
2014/06/27 PHP
php上传excel表格并获取数据
2017/04/27 PHP
PHP自定义序列化接口Serializable用法分析
2017/12/29 PHP
PHP defined()函数的使用图文详解
2019/07/20 PHP
laravel 字段格式化 modle 字段类型转换方法
2019/09/30 PHP
JavaScript For Beginners(转载)
2007/01/05 Javascript
jquery插件之easing 动态菜单
2010/08/21 Javascript
js实现适用于素材网站的黑色多级菜单导航条效果
2015/08/24 Javascript
温习Javascript基础语法之词法结构
2016/05/31 Javascript
Bootstrap Modal对话框如何在关闭时触发事件
2016/12/02 Javascript
jQuery插件echarts实现的去掉X轴、Y轴和网格线效果示例【附demo源码下载】
2017/03/04 Javascript
javascript Function函数理解与实战
2017/12/01 Javascript
Vue.js最佳实践(五招助你成为vuejs大师)
2018/05/04 Javascript
在vue中嵌入外部网站的实现
2020/11/13 Javascript
微信小程序实现弹幕墙(祝福墙)
2020/11/18 Javascript
[48:31]完美世界DOTA2联赛PWL S3 DLG vs Phoenix 第二场 12.17
2020/12/19 DOTA
python人民币小写转大写辅助工具
2018/06/20 Python
Python中Unittest框架的具体使用
2019/08/27 Python
Python生成验证码、计算具体日期是一年中的第几天实例代码详解
2019/10/16 Python
Python类继承和多态原理解析
2020/02/05 Python
python误差棒图errorbar()函数实例解析
2020/02/11 Python
PyQt5事件处理之定时在控件上显示信息的代码
2020/03/25 Python
Python使用内置函数setattr设置对象的属性值
2020/10/16 Python
美国知名的女性服饰品牌:LOFT(洛芙特)
2016/08/05 全球购物
皮尔·卡丹巴西官方商店:Pierre Cardin
2017/07/21 全球购物
Pop In A Box英国:Funko POP搪胶公仔
2019/05/27 全球购物
瑞典度假品牌:OAS
2019/05/28 全球购物
预备党员思想汇报
2014/01/08 职场文书
六一节目主持词
2014/04/01 职场文书
学期个人工作总结
2015/02/13 职场文书
党员学习中国梦心得体会
2016/01/05 职场文书
护理心得体会范文
2016/01/22 职场文书
Java面试题冲刺第十九天--数据库(4)
2021/08/07 Java/Android