题目1
Promise.resolve().then(() => {
console.log("p1");
setTimeout(() => {
console.log('s2')
}, 0)
})
setTimeout(() => {
console.log('s1');
Promise.resolve().then(() => {
console.log('p2');
})
})
分析
浏览器环境、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,此时都执行完成了
//promise1
Promise.resolve()
.then(() => {
console.log('p1');
//setTimeout2
setTimeout(() => {
console.log('s2');
}, 0)
})
//setTimeout1
setTimeout(() => {
console.log('s1');
//promise2
Promise.resolve().then(() => {
console.log('p2');
})
})
执行栈
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都放入进去了,依然可以得出正确答案,省得之后忘了,由于劳累、分心忘了,做题得出正确答案时可以这样做
// promise1
Promise.resolve()
.then(() => {
console.log('p1');
// setTimeout2-1
setTimeout(() => {
console.log('s2-1');
}, 0)
// setTimeout2-2
setTimeout(() => {
console.log('s2-2');
}, 0)
})
// setTimeout1
setTimeout(() => {
console.log('s1');
Promise.resolve()
// promise2-1
.then(() => {
console.log('p2-1');
})
// promise2-2
.then(() => {
console.log('p2-2');
})
}, 0)
执行栈
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