浅谈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代码
Apr 23 Javascript
JavaScript 面向对象的之私有成员和公开成员
May 04 Javascript
让你的博客飘雪花超出屏幕依然看得见
Jan 04 Javascript
jQuery prev ~ siblings选择器使用介绍
Aug 09 Javascript
JS小功能(列表页面隔行变色)简单实现
Nov 28 Javascript
js的touch事件的实际引用
Oct 13 Javascript
jQuery对象的selector属性用法实例
Dec 27 Javascript
JS中多种方式创建对象详解
Mar 22 Javascript
jQuery事件绑定用法详解
Sep 08 Javascript
bootstrap table复杂操作代码
Nov 01 Javascript
vue-cli如何添加less 以及sass
Jul 06 Javascript
Vuex实现简单购物车
Jan 10 Vue.js
返回上一个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
在Windows中安装Apache2和PHP4的权威指南
2006/10/09 PHP
PHP获取和操作配置文件php.ini的几个函数介绍
2013/06/24 PHP
php数组中包含中文的排序方法
2014/06/03 PHP
Yii框架弹出窗口组件CJuiDialog用法分析
2017/01/07 PHP
yii框架无限极分类的实现方法
2017/04/08 PHP
php+layui数据表格实现数据分页渲染代码
2019/10/26 PHP
PHP图像处理 imagestring添加图片水印与文字水印操作示例
2020/02/06 PHP
一段多浏览器的&quot;复制到剪贴板&quot;javascript代码
2007/03/27 Javascript
JS去掉第一个字符和最后一个字符的实现代码
2014/02/20 Javascript
js仿黑客帝国字母掉落效果代码分享
2020/11/08 Javascript
第九篇Bootstrap导航菜单创建步骤详解
2016/06/21 Javascript
javascript验证手机号和实现星号(*)代替实例
2016/08/16 Javascript
jQuery简单实现列表隐藏和显示效果示例
2016/09/12 Javascript
javascript滚轮事件基础实例讲解(37)
2017/02/14 Javascript
ES6使用let命令更简单的实现块级作用域实例分析
2017/03/31 Javascript
Vue作用域插槽slot-scope实例代码
2018/09/05 Javascript
从理论角度讨论JavaScript闭包
2019/04/03 Javascript
javascript面向对象三大特征之封装实例详解
2019/07/24 Javascript
解决使用layui对select append元素无效或者未及时更新的问题
2019/09/18 Javascript
[01:10:27]DOTA2-DPC中国联赛正赛 SAG vs XG BO3 第二场 3月5日
2021/03/11 DOTA
Python函数定义及传参方式详解(4种)
2019/03/18 Python
python requests证书问题解决
2019/09/05 Python
用Python写一个自动木马程序
2019/09/17 Python
win10下opencv-python特定版本手动安装与pip自动安装教程
2020/03/05 Python
快速解决jupyter notebook启动需要密码的问题
2020/04/21 Python
python使用bs4爬取boss直聘静态页面
2020/10/10 Python
修复iPhone的safari浏览器上submit按钮圆角bug
2012/12/24 HTML / CSS
用CSS3实现背景渐变的方法
2015/07/14 HTML / CSS
HTML5实现表单自动验证功能实例代码
2017/01/11 HTML / CSS
实例讲解使用SVG制作loading加载动画的方法
2016/04/05 HTML / CSS
运动会入场词60字
2014/02/15 职场文书
环保建议书作文
2014/03/12 职场文书
《郑和远航》教学反思
2014/04/16 职场文书
局火灾防控工作方案
2014/05/25 职场文书
意外伤害赔偿协议书范本
2014/09/28 职场文书
学习《中小学教师职业道德规范》心得体会
2016/01/18 职场文书