题目1

  1. Promise.resolve().then(() => {
  2. console.log("p1");
  3. setTimeout(() => {
  4. console.log('s2')
  5. }, 0)
  6. })
  7. setTimeout(() => {
  8. console.log('s1');
  9. Promise.resolve().then(() => {
  10. console.log('p2');
  11. })
  12. })

image.png

分析

浏览器环境、node环境,不同的环境可能结果不一样

先在代码上标注代码块标识,给起名字,省得忘记了
1执行栈中
Promise1.resolve().then()同步执行,把Promise1.then中的cb放入微任务队列中,回调函数异步执行
setTimeout1同步执行,把setTimeout1 cb放入宏任务队列中,并不是setTimeout不执行,它执行,而是它里面的回调函数什么时候处理的问题,回调函数异步执行,setTimeout1同步执行,setTimeout、then得(同步)运行,告诉浏览器它们里面的回调函数得异步处理,它们的作用就是这个,而不是执行回调函数,回调函数执行是在异步处理,微任务、宏任务中的事情了
2微任务队列全部执行,清空
Promise1.then cb推入js执行栈执行,(应该推入js执行栈,再执行,但简单就执行也行),console同步代码执行打印p1,setTimeout2是宏任务,执行把setTimeout2 cb放入宏任务队列中,清空微任务队列
3宏任务队列,处理第一个,推入js执行栈
把宏任务队列里面的setTimeout1 cb推入js执行栈
4js执行栈,第二次事件环
setTimeout1 cb1执行,console打印s1,Promise2.then cb放入微任务队列中
5微任务队列全部执行,清空
Promise2.then cb执行,打印p2
6宏任务队列
setTimeout2 cb2运行,打印s2,此时都执行完成了

  1. //promise1
  2. Promise.resolve()
  3. .then(() => {
  4. console.log('p1');
  5. //setTimeout2
  6. setTimeout(() => {
  7. console.log('s2');
  8. }, 0)
  9. })
  10. //setTimeout1
  11. setTimeout(() => {
  12. console.log('s1');
  13. //promise2
  14. Promise.resolve().then(() => {
  15. console.log('p2');
  16. })
  17. })

执行栈
promise1 then
setTimeout1

微任务队列
promise1 then cb x
console.log(p1)
promise2 then cb x
第二次eventloop循环
console.log(p2)
宏任务队列
setTimeout1 cb x
setTimeout2 cb2 x
console.log(s1)

console.log(s2)
所以是p1,s1,p2,s2

callback 回调 回来调用 cb

第一种写法
执行栈
promise.then cb->p1
setTimeout1 cb ->s1
promise2 cb ->p2
setTimeout2 ->s2

宏任务 setTimeout1 x setTimeout2 x
回调队列->setTimeout1 cb x setTimeout2 cb x

微任务 promise1 x promise2 x
回调队列->promise.then cb x promise2 cb x

第二种写法
执行栈
promise.then cb->p1
setTimeout1 cb ->s1
promise2 cb ->p2
setTimeout2 ->s2

宏任务
setTimeout1 x
setTimeout1 cb x
setTimeout2 x
setTimeout2 cb x

微任务
promise1 x
promise.then cb x
promise2 x
promise2 cb x

题目2

time 14m57s
与上面一题类似,但以下需要注意
在promise1 then cb运行时,setTimeout2-1、 setTimeout2-2是同步代码,都会运行,把setTimeout2-1 cb、 setTimeout2-2 cb放入宏任务队列中

当setTimeout1 cb执行时,promise2-1、promise2-2是链式调用,只会执行promise2-1,不会执行promise2-2,第二个then不会执行,因为链式调用,在promise中下一个then方法需要上一个then方法回调函数返回来的值,没有返回值不放入微任务队列中,得需要上一个then方法执行完成,有了返回值,第二个then方法才能运行

当清空微任务栈时,promise2-1 then cb运行,运行完promise2-2 then运行,把promise2-2 then cb放入微任务栈中,微任务栈-1+1,依然没有清空,还得继续运行微任务栈中的任务,直达清空,promise2-2 then cb运行,运行完,微任务栈终于清空了,
微任务队列中任务执行的时候,依然可能把微任务放入微任务队列中,这时需要再次运行,比如then链式调用,需要执行到微任务队列没有任务产生时
当then链式调用时,也可以理解成setTimeout1 cb运行是,将promise2-1、promise2-2都放入进去了,依然可以得出正确答案,省得之后忘了,由于劳累、分心忘了,做题得出正确答案时可以这样做

  1. // promise1
  2. Promise.resolve()
  3. .then(() => {
  4. console.log('p1');
  5. // setTimeout2-1
  6. setTimeout(() => {
  7. console.log('s2-1');
  8. }, 0)
  9. // setTimeout2-2
  10. setTimeout(() => {
  11. console.log('s2-2');
  12. }, 0)
  13. })
  14. // setTimeout1
  15. setTimeout(() => {
  16. console.log('s1');
  17. Promise.resolve()
  18. // promise2-1
  19. .then(() => {
  20. console.log('p2-1');
  21. })
  22. // promise2-2
  23. .then(() => {
  24. console.log('p2-2');
  25. })
  26. }, 0)

image.png

执行栈
Promise1.then cb->p1
setTimeout1 cb->s1
promise2-1 then cb ->p2-1

宏任务
setTimeout1 x
setTimeout1 cb x
setTimeout2-1
setTimeout2-1 cb
setTimeout2-2
setTimeout2-2 cb

微任务
Promise1 x
Promise1.then cb x
promise2-1 x
promise2-1 then cb x

??promise2-2
promise2-2 then cb

image.png

总结