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.注定它是单线程 ...
随机推荐
- Tweepy1——抓取Twitter数据
sklearn实战-乳腺癌细胞数据挖掘 https://study.163.com/course/introduction.htm?courseId=1005269003&utm_campai ...
- Hadoop生态圈-hbase常用命令
Hadoop生态圈-hbase常用命令 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.
- N制和PAL制区别
- Linux下查看系统版本和make版本
一.查看Linux内核版本命令(两种方法): 1.cat /proc/versionz [root@localhost ~]# cat /proc/versionLinux version 2.6.1 ...
- 使用前端组件化思想修改todolist
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- [hadoop]hadoop api 新版本与旧版本的差别
突然现在对以后的职业方向有些迷茫,不知道去干什么,现在有一些语言基础,相对而言好的一些有Java和C,选来选去不知道该选择哪个方向,爬了好多网页后,觉得自己应该从java开始出发,之前有点心不在焉,不 ...
- LintCode 158: Anagram
LintCode 158: Anagram 题目描述 写出一个函数anagram(s, t)判断两个字符串是否可以通过改变字母的顺序变成一样的字符串. 样例 给出s = "abcd" ...
- 【leetcode 简单】 第六十题 反转链表
反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶: 你可以迭代 ...
- scrapy 爬虫踩过的坑(II)
同事写了个爬虫,逻辑上看着没什么问题,但是一直报错:Request url must be str or unicode…… 打印了一下url 和url 的类型,确实是 unicode 懵逼…… 打印 ...
- 未来人类T5 安装win10,ubuntu双系统
1.首先确保win10已经安装,u盘中已刻录好系统,下载好英伟达最新驱动保存在u盘中,压缩100g的磁盘空间给ubuntu. 2.设置双显卡模式,重启时按F7选择进入u盘启动. 3.进入安装界面,选择 ...