JavaScript event loop事件循环 macrotask与microtask
macrotask 姑且称为宏任务,在很多上下文也被简称为task。例如:
setTimeout,
setInterval,
setImmediate,
I/O,
UI rendering.
microtask 微任务,也称job。例如:
process.nextTick,
Promise(原生),
Object.observe,
MutationObserver
备注:同时需要注意的是,在 ES 当中称 microtask 为 “jobs”。比如 ES6标准 8.4节当中的 “EnqueueJob” 意思指添加一个 microtask。

看看下面的实例:
setImmediate(function(){
console.log(1);
},0);
setTimeout(function(){
console.log(2);
},0);
new Promise(function(resolve){
console.log(3);
resolve();
console.log(4);
}).then(function(){
console.log(5);
});
console.log(6);
process.nextTick(function(){
console.log(7);
});
console.log(8);
//输出结果是3 4 6 8 7 5 2 1
看看另一题目
setTimeout(()=>{
console.log('A');
},0);
var obj={
func:function () {
setTimeout(function () {
console.log('B')
},0);
return new Promise(function (resolve) {
console.log('C');
resolve();
})
}
};
obj.func().then(function () {
console.log('D')
});
console.log('E');
1、首先 setTimeout A 被加入到事件队列中 ==> 此时macrotasks中有[‘A’];
2、obj.func()执行时,setTimeout B 被加入到事件队列中 ==> 此时macrotasks中有[‘A’,‘B’];
3、接着return一个Promise对象,Promise 新建后立即执行 执行console.log('C'); 控制台首次打印‘C’;
4、然后,then方法指定的回调函数,被加入到microtasks队列,将在当前脚本所有同步任务执行完才会执行。 ==> 此时microtasks中有[‘D’];
5、然后继续执行当前脚本的同步任务,故控制台第二次输出‘E’;
6、此时所有同步任务执行完毕,如上所述先检查microtasks队列,完成其中所有任务,故控制台第三次输出‘D’;
7、最后再执行macrotask的任务,并且按照入队列的时间顺序,控制台第四次输出‘A’,控制台第五次输出‘B’。
结果 C E D A B
setTimeout(function timeout () {
console.log('timeout');
},0);
setImmediate(function immediate () {
console.log('immediate');
});
结果
immediate
timeout
setInterval(function timeout () {
console.log('setInterval');
},0);
setTimeout(function timeout () {
console.log('timeout');
},0);
setImmediate(function immediate () {
console.log('immediate');
});
结果:
immediate
setInterval
timeout
setInterval
setTimeout(function timeout () {
console.log('timeout');
},0);setInterval(function timeout () {
console.log('setInterval');
},0);
timeout
setInterval
另一个
setTimeout(function timeout () {
console.log('timeout');
},0);
setImmediate(function immediate () {
console.log('immediate');
});
process.nextTick(function immediate () {
console.log('nickTick');
});
结果
nextTick
timeout
immediate
process.nextTick像是一个插入的tick. 生成了一个新的周期. 说白了, 是一个插队行为.
关于micro-task和macro-task的执行顺序,可看下面这个例子(来自《深入浅出Node.js》):
//加入两个nextTick的回调函数
process.nextTick(function () {
console.log('nextTick延迟执行1');
});
process.nextTick(function () {
console.log('nextTick延迟执行2');
});
// 加入两个setImmediate()的回调函数
setImmediate(function () {
console.log('setImmediate延迟执行1');
// 进入下次循环
process.nextTick(function () {
console.log('强势插入');
});
});
setImmediate(function () {
console.log('setImmediate延迟执行2');
}); console.log('正常执行')
书中给出的执行结果是:
正常执行
nextTick延迟执行1
nextTick延迟执行2
setImmediate延迟执行1
强势插入
setImmediate延迟执行2
process.nextTick在两个setImmediate之间强行插入了。
但运行这段代码发现结果却是这样:
正常执行
nextTick延迟执行1
nextTick延迟执行2
setImmediate延迟执行1
setImmediate延迟执行2
强势插入
朴老师写那本书的时候,node最新版本为0.10.13,而我的版本是6.x
JavaScript event loop事件循环 macrotask与microtask的更多相关文章
- javascript的event loop事件循环
javascript的event loop事件循环 这是今天一个朋友发给我的一个面试题, 感觉还挺有意思的, 写个博客以供分享 先看看这个面试题目: 观察下面的代码,写出输出结果 console.lo ...
- 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?
https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...
- Event Loop事件循环,GET!
JS中比较让人头疼的问题之一要算异步事件了,比如我们经常要等后台返回数据后进行dom操作,又比如我们要设置一个定时器完成特定的要求.在这些同步与异步事件里,异步事件肯定是在同步事件之后的,但是异步事件 ...
- node.js中对Event Loop事件循环的理解
javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务. 同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行. 异步任务是不进 ...
- 浅谈 Event loop (事件循环)
从Event Loop谈JS的运行机制 先来理解一个概念: JS分为同步任务和异步任务 同步任务都在主线程上执行,形成一个执行栈 Execute Content Stack 主线程之外,事件触发线程管 ...
- 进程,线程,Event Loop(事件循环),Web Worker
线程,是程序执行流的最小单位.线程可与同属一个进程的其他线程共享所拥有的全部资源,同一进程中的多个线程之间可以并发执行.线程有就绪,阻塞,运行三种基本状态. 阮一峰大神针对进程和线程的类比,很是形象: ...
- js event loop事件循环
浏览器环境 以下两段代码是等价的.req对事件的回调设置,实际上就是当前主线程任务队列的任务. var req = new XMLHttpRequest(); req.open('GET', url) ...
- JavaScript中的事件循环
JavaScript是单线程单并发语言 单线程:主程序只有一个线程,即同一时间片段内其只能执行单个任务. 引发的问题: 单线程,意味着任务都需要排队,前一个任务结束,才会执行后一个任务.若前一个任务耗 ...
- JavaScript Event Loop和微任务、宏任务
为什么JavaScript是单线程? JavaScript的一大特点就是单线程, 同一时间只能做一件事情,主要和它的用途有关, JavaScript主要是控制和用户的交互以及操作DOM.注定它是单线程 ...
随机推荐
- P1978 集合
P1978 集合 题目描述 集合是数学中的一个概念,用通俗的话来讲就是:一大堆数在一起就构成了集合.集合有如 下的特性: •无序性:任一个集合中,每个元素的地位都是相同的,元素之间是无序的. •互异性 ...
- ffmpeg的API函数用法 :sws_scale函数的用法-具体应用
移植ffmpeg过程中,遇到swscale的用法问题,所以查到这篇文章.文章虽然已经过去很长时间,但是还有颇多可以借鉴之处.谢谢“咕咕钟. 转自:http://guguclock.blogspot.c ...
- git 提交模板配置
1.创建模板文件,比如gitTemplate.txt,内容如下: ABSTRACT:修改自测发现的多度数据同步相关问题. Bug Fix [Y/N]:NBug ID:New Feature [Y/N] ...
- 大数据时代快速SQL引擎-Impala
背景 随着大数据时代的到来,Hadoop在过去几年以接近统治性的方式包揽的ETL和数据分析查询的工作,大家也无意间的想往大数据方向靠拢,即使每天数据也就几十.几百M也要放到Hadoop上作分析,只会适 ...
- 20155325 2016-2017-2 《Java程序设计》第5周学习总结
教材学习内容总结 Java中把正常流程放try块中,错误(异常)处理放catch块中. Error及其子类写程序不用处理,最多留个日志.因为这种错误Java应用程序本身是无力回复的. 在使用throw ...
- Google Congestion Control介绍
随着网络带宽的日益增加和便携式设备,如智能手机或平板电脑处理能力的增强,基于互联网的实时通信已经成为热点. 虽然视频会议已商用了多年,特别是SKYPE这样的视频应用在互联网上已有10年时间,但针对实时 ...
- JavaScript逻辑运算符
逻辑运算符 或与非:&& || ! ----------------------------------------------------------- ...
- php strcmp()函数
<? $str = "LAMP"; $str1 = "LAMPBrother"; $strc = strcmp($str,$str1); switch ( ...
- es6解构、中括号前加分号
在写项目的时候,为了方便使用了下对象的解构,无奈又遇到一坑. 为什么会不能解构呢?因为这里的{}会导致歧义,因为 JavaScript 引擎会将{xxxxx}理解成一个代码块,从而发生语法错误.只有不 ...
- Go net/http获取body中json格式数据
Go net/http获取body中json格式数据 package main import ( "encoding/json" "fmt" "io/ ...