浅析setTimeout与Promise

我们先看一到常见的前端面试题:

var p1 = new Promise(function(resolve, reject){
    resolve(1);
})
setTimeout(function(){
  console.log("will be executed at the top of the next Event Loop");
},0)
p1.then(function(value){
  console.log("p1 fulfilled");
})
setTimeout(function(){
  console.log("will be executed at the bottom of the next Event Loop");
},0)

上例代码执行输出顺序如何?这道题也是本文创作的源泉,其答案是:

p1 fulfilled
will be executed at the top of the next Event Loop
will be executed at the bottom of the next Event Loop

异步任务



回顾JavaScript事件循环并发模型,我们了解了setTimeout和Promise调用的都是异步任务,这一点是它们共同之处,也即都是通过任务队列进行管理/调度。那么它们有什么区别吗?下文继续介绍。

任务队列

前文已经介绍了任务队列的基础内容和机制,可选择查看,本文对任务队列进行拓展介绍。JavaScript通过任务队列管理所有异步任务,而任务队列还可以细分为MacroTask Queue和MicoTask Queue两类。

MacroTask Queue

MacroTask Queue(宏任务队列)主要包括setTimeout,setInterval, setImmediate, requestAnimationFrame, NodeJS中的`I/O等。

MicroTask Queue

MicroTask Queue(微任务队列)主要包括两类:

独立回调microTask:如Promise,其成功/失败回调函数相互独立;
复合回调microTask:如 Object.observe, MutationObserverNodeJs中的 process.nextTick ,不同状态回调在同一函数体;

MacroTask和MicroTask

JavaScript将异步任务分为MacroTask和MicroTask,那么它们区别何在呢?

依次执行同步代码直至执行完毕;
检查MacroTask 队列,若有触发的异步任务,则取第一个并调用其事件处理函数,然后跳至第三步,若没有需处理的异步任务,则直接跳至第三步;
检查MicroTask队列,然后执行所有已触发的异步任务,依次执行事件处理函数,直至执行完毕,然后跳至第二步,若没有需处理的异步任务中,则直接返回第二步,依次执行后续步骤;
最后返回第二步,继续检查MacroTask队列,依次执行后续步骤;
如此往复,若所有异步任务处理完成,则结束;

链接:https://juejin.im/post/5b7057b251882561381e69bf

你可能感兴趣的:(浅析setTimeout与Promise)