setTimeout和Promise进行混合操作的执行顺序

宏任务包含:

script(整体代码)
setTimeout
setInterval
I/O
UI交互事件
postMessage
MessageChannel
setImmediate(Node.js 环境)
执行new Promise的时候是个宏任务


微任务:

Promise.then
Object.observe
MutationObserver
process.nextTick(Node.js 环境)
console.log('同步-0.1')
Promise.resolve().then(() => {
  console.log('P-1.1')
})
setTimeout(() => {
  console.log('S-1.1')
});
Promise.resolve().then(() => {
  console.log('P-1.2')
})
setTimeout(() => {
  console.log('S-1.2')
});
console.log('同步-0.2')

执行结果如下。。。问题暴露出来了:

我顺便说下,会先把所有的同步代码执行后,才会开始异步,所以第二条才会输出:同步-0.2

setTimeout不会马上执行,是会放到队列事件里面

同步-0.1
同步-0.2
P-1.1
P-1.2
S-1.1
S-1.2

 抛出问题:为什么,在同级情况下,是Promise执行完了setTimeout才会执行?

JavaScript的任务分为微任务(Microtasks)和宏任务(task);

  • 宏任务是主流,当js开始被执行的时候,就是开启一个宏任务,在宏任务中执行一条一条的指令;
  • 宏任务可以同时有多个,但会按顺序一个一个执行;
  • 每一个宏任务,后面都可以跟一个微任务队列,如果微任务队列中有指令或方法,那么就会执行;如果没有,则开始执行下一个宏任务,直到所有的宏任务执行完为止,微任务相当于宏任务的小尾巴;
  • 为什么有了宏任务,还会有微任务存在?因为宏任务太占用性能,当需要一些较早就准备好的方法,排在最后才执行的时候,又不想新增一个宏任务,那么就可以把这些方法,一个一个的放在微任务队列里面,在这个宏任务中的代码执行完后,就会执行微任务队列。

Promise是微任务,setTimeout是宏任务。

所以上面的代码中,代码执行时会是如下场景:

开始执行当前宏任务代码!

遇到了Promise?好嘞,把它里面的异步代码,放在当前这个宏任务后面微任务里面,然后继续执行咱的;

咦,有个setTimeout?是个宏任务,那在当前这个宏任务后面,创建第二个宏任务,然后把这个setTimeout里面的代码塞进去,咱继续执行;

咦,又一个Promise?把他塞进后面的微任务里。。。什么?已经有代码了?那有啥关系,继续往里塞,放在已有代码的后面就行,咱继续执行;

天啊,又来一个setTimeout,现在后面已经有第二个宏任务了对吧?那就创建第三个宏任务吧,后面再遇到的话,继续创建;

报告!代码执行到底了,当前这个宏任务执行完毕!
行,看一下咱的小尾巴---咱的微任务里面有代码吗?有的话直接执行;

报告,微任务里面,那两个Promise的异步代码执行完了!
干的漂亮。。。对了,刚刚微任务里面,有没有新的Promise微任务?有的话,继续在现在这个微任务后面放!对对,只看执行到的代码,有多少放多少,一会儿直接就执行了。。。如果遇到了setTimeout知道该怎么做吧?继续开宏任务!

报告,微任务全部执行完毕!

好!开始执行下一个宏任务!

所以,现在如果执行下面的代码,结果也显而易见吧:

console.log('同步-0.1')
Promise.resolve().then(() => {
  console.log('P-1.1')
  Promise.resolve().then(() => { // 新加行
    console.log('P-2.1') // 新加行
    Promise.resolve().then(() => { // 新加行
      console.log('P-3.1') // 新加行
    }) // 新加行
  }) // 新加行
})
setTimeout(() => {
  console.log('S-1.1')
});
Promise.resolve().then(() => {
  console.log('P-1.2')
})
setTimeout(() => {
  console.log('S-1.2')
});
console.log('同步-0.2')

答案:
同步-0.1
同步-0.2
P-1.1
P-1.2
P-2.1
P-3.1
S-1.1
S-1.2

结论:无论Promise套用多少层,都会在下一个setTimeout之前执行完Promise。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值