2020年7月15日(event loop)


先看一段代码

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**,执行完后清空微任务队中的任务,接着执行宏任务队中的第二个任务,依次循环

7515749-2e1fcbed128544cb

宏任务有:

  • 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最后输出。

阮一峰 event loop

阮一峰 Node定时器


Author: wxy
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source wxy !
  TOC