我们先来看一段代码
process.nextTick(()=>{console.log(1)});
setTimeout(()=>{console.log(2)},0);
setImmediate(()=>{console.log(3) ;process.nextTick(()=>{console.log(4)})});
new Promise((res,rej)=>{console.log(7);res()}).then(()=>{console.log(5)})
console.log(6)
上述这段代码的执行结果是7,6,1,5,2,3,4。这是为什么呢?
首先在js中分有宏观任务(macro-task)和微观任务(micro-task)。宏观任务顺序为setTimeout,setInterval,setImmediate,微观任务有process.nextTick,Promise。再来看代码,这几个任务里面的回调函数都是异步的,而Promise里面的then才是异步的,即console.log(7)是同步的。在执行过程中它会先执行同步的代码,所以首先打印出7和6。然后它会执行微观任务的代码,即process.nextTick和promise中then里的回调,所以打印了1和5,接着再执行宏观任务的代码,即setTimeout和setImmediate,所以打印出2和3,而setImmediate中又包含了process.nextTick,所以他会插入微观任务队列里面,宏观任务执行完毕便清空队列,然后又执行微观任务队列里面的函数,即打印出4.
再来看一个例子
setImmediate(()=>{console.log(5);process.nextTick(()=>{console.log(6)})})
setTimeout(()=>{console.log(1)},0);
process.nextTick(()=>{console.log(2);
new Promise((res,rej)=>{console.log(3);res()}).then(()=>{console.log(4)})
})
首先读取代码可以得到宏观任务setTimeout和setImmediate,微观任务process.nextTick和Promise,所以首先先执行微观任务,打印出2,然后因为Promise里面是同步的,所以接着打印出3和4,然后执行宏观任务队列里面的setTimeout和setImmediate,打印出1和5,然后因为setImmediate里面有process.nextTick,所以插入微观任务队列,再执行微观任务队列里的process.nextTick打印出6