宏任务,微任务中setTimeout和promise.then的执行顺序

代码:

const promise1= new Promise((resolve,reject)=>{
  console.log('promise1');
  setTimeout(()=> {
    resolve('success promise1')
  })
})

const promise2 = promise1.then(() => {
  console.log('success promise2');
  return 666;
})

const promise3 = promise2.then(res => {
  console.log('success promise3:', res);
  return Promise.resolve(818);
  
})

promise3.then((res) => {
  console.log('success promise4:',res);
})

setTimeout(()=> {
  console.log('timer duration=10')
}, 10)

setTimeout(()=> {
  console.log('timer duration=0')
}, 0)

console.log('just test')

顺序分析:

new Promise内部代码直接执行,所以先输出promise1setTimeout将回调函数交于定时器线程管理,待当前宏任务队列清空后立即推入宏任务队列并执行。
上一步new Promise返回的promise赋值给promise1,而promise1此时并未resolve,所以将then的内容缓存到[[PromiseFulfill/RejectReactions]]列表。待promise1 resolve之后,才将then中的内容推入微任务队列。这里依赖promise1fullfilled状态
promise3 的值依赖promise2的状态,由于promise1此时状态未改变,所以promise2也未变。
遇到setTimeout,交于定时器线程管理,10ms后若主线程任务已清空则将代码推入宏任务队列。
遇到setTimeout,交于定时器线程管理,0ms后若主线程任务已清空则将代码推入宏任务队列。
直接输出just test。
第一次宏任务执行完毕,当前任务队列已清空。此时定时器线程将resolve('success promise1')推入宏任务队列并执行,进入第二轮事件循环。
promise1状态被改变,promise1.then被推入微任务队列并执行。
promise2状态被改变,promise2.then被推入微任务队列并执行。
promise3状态被改变,promise3.then被推入微任务队列并执行。
微任务执行完毕,当前无任务,第二轮事件循环结束,定时器将console.log(timer duration=0)推入宏任务队列,进入第三轮事件循环,输出timer duration=0后第三轮事件循环结束。
此时若未过10ms,则等待至10ms后,将console.log('timer duration=10')推入宏任务队列并执行,第四轮事件循环结束。
结果输出:

"promise1"
"just test"
"success promise2"
"success promise3:" 666
"success promise4:" 818
"timer duration=0"
"timer duration=10"

setTimeout设置的时间,0和1都一样,如果设置为2,那么将晚与0或1执行,比如将promise1的地方改成如下

setTimeout(()=> {
    resolve('success promise1')
}, 2)

输出将变为:

"promise1"
"just test"
"timer duration=0"
"success promise2"
"success promise3:" 666
"success promise4:" 818
"timer duration=10"

————————————————
原文转自好友qingxuepeng

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容