浅谈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 相关文章推荐
用jscript实现新建word文档
Jun 15 Javascript
javascript检测浏览器flash版本的实现代码
Dec 06 Javascript
jquery实现div拖拽宽度示例代码
Jul 31 Javascript
java与javascript之间json格式数据互转介绍
Oct 29 Javascript
深入理解jquery自定义动画animate()
May 24 Javascript
JS中使用apply方法通过不同数量的参数调用函数的方法
May 31 Javascript
详解node.js 下载图片的 2 种方式
Mar 02 Javascript
bootstrap table实现合并单元格效果
Dec 24 Javascript
TypeScript中使用getElementXXX()的示例代码
Sep 12 Javascript
node.js基础知识汇总
Aug 25 Javascript
Element-UI 使用el-row 分栏布局的教程
Oct 26 Javascript
javascript实现固定侧边栏
Feb 09 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
IStream与TStream之间的相互转换
2008/08/01 PHP
ThinkPHP验证码使用简明教程
2014/03/05 PHP
php+mysql不用递归实现的无限级分类实例(非递归)
2014/07/08 PHP
详解PHP的Laravel框架中Eloquent对象关系映射使用
2016/02/26 PHP
TP框架实现上传一张图片和批量上传图片的方法分析
2020/04/23 PHP
jQuery学习笔记之jQuery.extend(),jQuery.fn.extend()分析
2014/06/09 Javascript
jquery实现一个简单好用的弹出框
2014/09/26 Javascript
Node.js中的流(Stream)介绍
2015/03/30 Javascript
js数组去重的方法汇总
2015/07/29 Javascript
Node.js环境下编写爬虫爬取维基百科内容的实例分享
2016/06/12 Javascript
深入探究AngularJs之$scope对象(作用域)
2017/07/20 Javascript
angular.js4使用 RxJS 处理多个 Http 请求
2017/09/23 Javascript
[17:36]VG战队纪录片
2014/08/21 DOTA
python实现360的字符显示界面
2014/02/21 Python
pandas 两列时间相减换算为秒的方法
2018/04/20 Python
解决python3 Pycharm上连接数据库时报错的问题
2018/12/03 Python
django框架防止XSS注入的方法分析
2019/06/21 Python
10分钟教你用python动画演示深度优先算法搜寻逃出迷宫的路径
2019/08/12 Python
pytorch自定义二值化网络层方式
2020/01/07 Python
python数字类型math库原理解析
2020/03/02 Python
网页切图的CSS和布局经验与要点
2015/04/09 HTML / CSS
Kipling凯浦林美国官网:世界著名时尚休闲包袋品牌
2016/08/24 全球购物
兰蔻法国官方网站:Lancôme法国
2020/02/22 全球购物
我有一个char * 型指针正巧指向一些int 型变量, 我想跳过它们。 为什么如下的代码((int *)p)++; 不行?
2013/05/09 面试题
暑期实践思想汇报
2014/01/06 职场文书
审计主管岗位职责
2014/01/31 职场文书
电气个人求职信范文
2014/02/04 职场文书
取保候审保证书
2014/04/30 职场文书
葬礼主持词
2015/07/02 职场文书
运动会通讯稿100字
2015/07/20 职场文书
2015年第31个教师节致辞
2015/07/31 职场文书
如果用一句诗总结你的上半年,你会用哪句呢?
2019/07/16 职场文书
2019年家电促销广告语集锦
2019/10/21 职场文书
吃通javascript正则表达式
2021/04/21 Javascript
用python实现监控视频人数统计
2021/05/21 Python
sqlserver连接错误之SQL评估期已过的问题解决
2022/03/23 SQL Server