浅谈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 相关文章推荐
文件编码导致jquery失效的解决方法
Jun 26 Javascript
JQuery分别取得每行最后一列和最后一行的示例代码
Aug 18 Javascript
解决jquery操作checkbox火狐下第二次无法勾选问题
Feb 10 Javascript
jquery ajaxSubmit 异步提交的简单实现
Feb 28 Javascript
jquery easyui 对于开始时间小于结束时间的判断示例
Mar 22 Javascript
使用js实现数据格式化
Dec 03 Javascript
jquery渐隐渐显的图片幻灯闪烁切换实现方法
Feb 26 Javascript
JavaScript利用闭包实现模块化
Jan 13 Javascript
js实现上传并压缩图片效果
Jan 10 Javascript
基于vue-simplemde实现图片拖拽、粘贴功能
Apr 12 Javascript
微信小程序引入VANT组件的方法步骤
Sep 19 Javascript
vue实现一个6个输入框的验证码输入组件功能的实例代码
Jun 29 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/03/04 PHP
php实现的Timer页面运行时间监测类
2014/09/24 PHP
PHP快速生成各种信息提示框的方法
2016/02/03 PHP
PHP基于XMLWriter操作xml的方法分析
2017/07/17 PHP
php抽象方法和普通方法的区别点总结
2019/10/13 PHP
javascript获得CheckBoxList选中的数量
2009/10/27 Javascript
Javascript学习笔记二 之 变量
2010/12/15 Javascript
JavaScript的各种常见函数定义方法
2014/09/16 Javascript
JQuery遍历元素的父辈和祖先的方法
2016/09/18 Javascript
BootStrap实现响应式布局导航栏折叠隐藏效果(在小屏幕、手机屏幕浏览时自动折叠隐藏)
2016/11/30 Javascript
Jquery EasyUI Datagrid右键菜单实现方法
2016/12/30 Javascript
简单谈谈Javascript函数中的arguments
2017/02/09 Javascript
JQueryMiniUI按照时间进行查询的实现方法
2017/06/07 jQuery
vue中的非父子间的通讯问题简单的实例代码
2017/07/19 Javascript
vue.js组件vue-waterfall-easy实现瀑布流效果
2017/08/22 Javascript
Vue.js 踩坑记之双向绑定
2018/05/03 Javascript
vue+axios新手实践实现登陆的示例代码
2018/06/06 Javascript
微信小程序image图片加载完成监听
2019/08/31 Javascript
layui实现给某一列加点击事件
2019/10/26 Javascript
[01:24:34]2014 DOTA2华西杯精英邀请赛5 24 DK VS LGD
2014/05/25 DOTA
[01:07:34]DOTA2-DPC中国联赛定级赛 RNG vs Aster BO3第二场 1月9日
2021/03/11 DOTA
python使用pil生成图片验证码的方法
2015/05/08 Python
详解Python中的array数组模块相关使用
2016/07/05 Python
用Eclipse写python程序
2018/02/10 Python
python实现推箱子游戏
2020/03/25 Python
Python QQBot库的QQ聊天机器人
2019/06/19 Python
python使用Thread的setDaemon启动后台线程教程
2020/04/25 Python
CSS+jQuery+PHP+MySQL实现的在线答题功能
2015/04/25 HTML / CSS
建筑设计师岗位职责
2013/11/18 职场文书
教师旷工检讨书
2014/01/18 职场文书
给水工程专业毕业生自荐信
2014/01/28 职场文书
文明寄语大全
2014/04/11 职场文书
教师考察材料范文
2014/06/03 职场文书
大学专科求职信
2014/07/02 职场文书
开学第一周总结
2015/07/16 职场文书
Python必备技巧之函数的使用详解
2022/04/04 Python