浅谈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 相关文章推荐
js DOM的学习笔记
Dec 22 Javascript
Jquery的each里用return true或false代替break或continue
May 21 Javascript
JavaScript动态生成二维码图片
Apr 20 Javascript
JavaScript兼容性总结之获取非行间样式案例
Aug 07 Javascript
javascript中this用法实例详解
Apr 06 Javascript
微信小程序中多个页面传参通信的学习与实践
May 05 Javascript
jquery.uploadView 实现图片预览上传功能
Aug 10 jQuery
浅谈Vue父子组件和非父子组件传值问题
Aug 22 Javascript
JavaScript实现数值自动增加动画
Dec 28 Javascript
bootstrap下拉框动态赋值方法
Aug 10 Javascript
原生JS实现$.param() 函数的方法
Aug 10 Javascript
解决vue打包报错Unexpected token: punc的问题
Oct 24 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字符串的递增和递减示例介绍
2014/02/11 PHP
yii实现CheckBox复选框在同一行显示的方法
2014/12/03 PHP
php递归遍历多维数组的方法
2015/04/18 PHP
PHP判断是手机端还是PC端 PHP判断是否是微信浏览器
2017/03/15 PHP
PHP 并发场景的几种解决方案
2019/06/14 PHP
面向对象的javascript(笔记)
2009/10/06 Javascript
Exitjs获取DataView中图片文件名
2009/11/26 Javascript
基于jQuery的Spin Button自定义文本框数值自增或自减
2010/07/17 Javascript
poshytip 基于jquery的 插件 主要用于显示微博人的图像和鼠标提示等
2012/10/12 Javascript
js调试系列 初识控制台
2014/06/18 Javascript
JavaScript中具名函数的多种调用方式总结
2014/11/08 Javascript
nodejs中的fiber(纤程)库详解
2015/03/24 NodeJs
Node.js插件安装图文教程
2016/05/06 Javascript
jQuery获取当前点击的对象元素(实现代码)
2016/05/19 Javascript
AngularJs 指令详解及示例代码
2016/09/01 Javascript
JavaScript设计模式之单例模式详解
2017/06/09 Javascript
js实现以最简单的方式将数组元素添加到对象中的方法
2017/12/20 Javascript
jQuery实现table表格信息的展开和缩小功能示例
2018/07/21 jQuery
vue+canvas实现炫酷时钟效果的倒计时插件(已发布到npm的vue2插件,开箱即用)
2018/11/05 Javascript
OpenLayers3实现图层控件功能
2020/09/25 Javascript
Python with的用法
2014/08/22 Python
python 列表转为字典的两个小方法(小结)
2019/06/28 Python
python 实现list或string按指定分段
2019/12/25 Python
Django Channel实时推送与聊天的示例代码
2020/04/30 Python
让Django的BooleanField支持字符串形式的输入方式
2020/05/20 Python
新手学python应该下哪个版本
2020/06/11 Python
细说NumPy数组的四种乘法的使用
2020/12/18 Python
python绘制汉诺塔
2021/03/01 Python
会计专业应届生自荐信
2014/02/07 职场文书
共产党员公开承诺书范文
2014/03/28 职场文书
公证书标准格式
2014/04/10 职场文书
优秀护士演讲稿
2014/04/30 职场文书
2015年大学班主任工作总结
2015/04/30 职场文书
幼儿园六一主持词
2015/06/30 职场文书
Python pyecharts绘制条形图详解
2022/04/02 Python
详解Python中的for循环
2022/04/30 Python