先看一段代码
setTimeout(function(){console.log(1)},0);
new Promise(function(resolve,reject){
console.log(2);
resolve();
}).then(function(){console.log(3)
}).then(function(){console.log(4)});
process.nextTick(function(){console.log(5)});
console.log(6);
//输出2,6,5,3,4,1
具体原因呢?
从promise、process.nextTick、setTimeout出发,谈谈Event Loop中的任务队列
event loop,是指主线程从“任务队列”中循环读取任务
//例1:
setTimeout(function(){console.log(1)},0);
console.log(2)
//打印2,1
当主线程任务执行完毕后,再从event loop中读取任务,因此先输出2,再输出1。
任务队列的执行顺序
任务队列分为两种类型,宏任务和微任务
宏任务队列包含任务: a1, a2 , a3
微任务队列包含任务: b1, b2 , b3
执行顺序为,首先执行宏任务队列开头的任务,也就是 a1 任务,执行完毕后,在执行微任务队列里的所有任务,也就是依次执行**b1, b2 , b3**,执行完后清空微任务队中的任务,接着执行宏任务队中的第二个任务,依次循环
宏任务有:
- setTimeout
- setInterval
- setImmediate
- requestAnimationFrame
- I/O
微任务
- process.nextTick
- pormise.then
- Object.observe
执行顺序应该为:
script(主程序代码)—>process.nextTick—>Promises…——>setTimeout——>setInterval——>setImmediate——> I/O——>UI rendering
process.nextTick() 是 Node 的一个定时器,让任务可以在指定的时间运行。其中 Node 一共提供了 4 个定时器,它们分别是 setTimeout()、setInterval()、setImmediate()、process.nextTick()
process.nextTick它是在本轮循环执行的,而且是所有异步任务里面最快执行的。
(1) setTimeout和promise
//例3:
setTimeout(function () {
console.log(3);
}, 0);
Promise.resolve().then(function () {
console.log(2);
});
console.log(1);
script(主程序代码)——>promise——>setTimeout
对应的输出依次为:1 ——>2——>3
(2) process.nextTick和promise、setTimeout
例子4:
setTimeout(function(){console.log(1)},0);
new Promise(function(resolve,reject){
console.log(2);
resolve();
}).then(function(){console.log(3)
}).then(function(){console.log(4)});
process.nextTick(function(){console.log(5)});
console.log(6);
//输出2,6,5,3,4,1
promise构造部分是同步执行的
执行顺序:
script(主程序代码)——>process.nextTick——>promise——>setTimeout
合的执行顺序就是: 2——>6——>5——>3——>4——>1
接下来例子
setTimeout(function(){console.log(1)},0);
new Promise(function(resolve,reject){
console.log(2);
setTimeout(function(){resolve()},0)
}).then(function(){console.log(3)
}).then(function(){console.log(4)});
process.nextTick(function(){console.log(5)});
console.log(6);
//输出的是 2 6 5 1 3 4
跟上面的例子不一样因为promise中没有同步的resolve,所以promise.then在当前的执行队列中是不存在的,只有promise从pending转移到resolve,才会有then方法,而这个resolve是在一个setTimout时间中完成的,因此3,4最后输出。