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的更多相关文章

  1. javascript的event loop事件循环

    javascript的event loop事件循环 这是今天一个朋友发给我的一个面试题, 感觉还挺有意思的, 写个博客以供分享 先看看这个面试题目: 观察下面的代码,写出输出结果 console.lo ...

  2. 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?

    https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...

  3. Event Loop事件循环,GET!

    JS中比较让人头疼的问题之一要算异步事件了,比如我们经常要等后台返回数据后进行dom操作,又比如我们要设置一个定时器完成特定的要求.在这些同步与异步事件里,异步事件肯定是在同步事件之后的,但是异步事件 ...

  4. node.js中对Event Loop事件循环的理解

    javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务. 同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行. 异步任务是不进 ...

  5. 浅谈 Event loop (事件循环)

    从Event Loop谈JS的运行机制 先来理解一个概念: JS分为同步任务和异步任务 同步任务都在主线程上执行,形成一个执行栈 Execute Content Stack 主线程之外,事件触发线程管 ...

  6. 进程,线程,Event Loop(事件循环),Web Worker

    线程,是程序执行流的最小单位.线程可与同属一个进程的其他线程共享所拥有的全部资源,同一进程中的多个线程之间可以并发执行.线程有就绪,阻塞,运行三种基本状态. 阮一峰大神针对进程和线程的类比,很是形象: ...

  7. js event loop事件循环

    浏览器环境 以下两段代码是等价的.req对事件的回调设置,实际上就是当前主线程任务队列的任务. var req = new XMLHttpRequest(); req.open('GET', url) ...

  8. JavaScript中的事件循环

    JavaScript是单线程单并发语言 单线程:主程序只有一个线程,即同一时间片段内其只能执行单个任务. 引发的问题: 单线程,意味着任务都需要排队,前一个任务结束,才会执行后一个任务.若前一个任务耗 ...

  9. JavaScript Event Loop和微任务、宏任务

    为什么JavaScript是单线程? JavaScript的一大特点就是单线程, 同一时间只能做一件事情,主要和它的用途有关, JavaScript主要是控制和用户的交互以及操作DOM.注定它是单线程 ...

随机推荐

  1. Hadoop生态圈-HBase的HFile创建方式

    Hadoop生态圈-HBase的HFile创建方式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 废话不多说,直接上代码,想说的话都在代码的注释里面. 一.环境准备 list cr ...

  2. Java锁及AbstractQueuedSynchronizer源码分析

    一,Lock 二,关于锁的几个概念 三,ReentrantLock类图 四,几个重要的类 五,公平锁获取 5.1 lock 5.2 acquire 5.3 tryAcquire 5.3.1 hasQu ...

  3. jquery radio的操作

    radio 按钮组, name=”sex”. <input type="radio" name="sex" value="Male"& ...

  4. zookeeper图形工具——zkui

    虽然zookeeper安装包提供了客户端工具zkcli,但是命令特别少 ,每次想看看里面的节点信息特别费劲. 幸好有图形工具——zkui,https://github.com/echoma/zkui, ...

  5. ASP.NET项目与IE10、IE11不兼容的解决办法

    1.解决办法 机器级别修复, 服务器所有ASP.NET程序受益 需要去微软下载对应asp.NET版本的修补程序 .NET 4 -http://support.microsoft.com/kb/2600 ...

  6. 【疑点】<p></p>标签为什么不能包含块级标签?还有哪些特殊的HTML标签?

    最近,在码代码的时候,就是下面的这段代码,我犯了一个很不起眼,但犯了就致命的BUG. <body> <p> <ol> <li>Hello</li& ...

  7. 【环境变量】Linux 下三种方式设置环境变量与获取环境变量

    1.在Windows 系统下,很多软件安装都需要配置环境变量,比如 安装 jdk ,如果不配置环境变量,在非软件安装的目录下运行javac 命令,将会报告找不到文件,类似的错误. 2.那么什么是环境变 ...

  8. ORA-00906 missing left parenthesis括号

    Oracle 建表报错:ORA-00906 missing left parenthesis括号    建表语句:create table test(id char,name varchar(1),s ...

  9. Gh0st配置加密与解密算法(异或、Base64)

    1.前言 分析木马程序常常遇到很多配置信息被加密的情况,虽然现在都不直接分析而是通过Wireshark之类的直接读记录. 2017年Gh0st样本大量新增,通过对木马源码的分析还发现有利用Gh0st加 ...

  10. Linux configure关于交叉编译的参数设置【转】

    转自:http://blog.csdn.net/darennet/article/details/9003005 configure的参数众多,一般包括如下 --srcdir=DIR 这个选项对安装没 ...