规则1 : 连续链式的微任务,只有第一个会进入微任务队列
规则2 : 当在then 去return时,这个return是需要去执行出终的结果值的,也就是说,如果返回的promise产生了微任务的话,会尝试从微任务队列去取出这个微任务,执行拿出结果最终结果
解析promise题目时,需要理解js事件循环的原理和js宏微任务具体是什么,然后牢记以上两条规则,否则不建议继续往下看。
new Promise((resolve, reject) => { // Promise1
console.log("外部promise");
resolve();
})
.then(() => {
// then1
console.log("外部第一个then");
new Promise((resolve, reject) => { // Promise2
console.log("内部promise");
resolve();
})
.then(() => {
// then2
console.log("内部第一个then");
})
.then(() => {
// then3
console.log("内部第二个then");
});
return new Promise((resolve, reject) => { // Promise3
console.log("内部promise2");
resolve();
})
.then(() => {
// then4
console.log("内部第一个then");
})
.then(() => {
// then5
console.log("内部第二个then2");
});
})
.then(() => {
//// then6
console.log("外部第二个then");
});
结合实际情况,下面给这道promise解析出答案的流程,清晰了解两条规则,并往下理解出执行流程,promise面试题都可以迎刃而解。
解析结果:
首次执行代码: 执行promise内部回调,打印外部promise,reslove()后,由于链式了then,产生了一个微任务。 我们给这个一个then 命名为 then1。
当前微任务队列: [then1]
事件循环:优先微任务 :找到 then1 ,取进主线程执行,下面是执行流程: 1、执行同步 首先 "外部第一个then" 2、 执行 then1 内部第一个promise回调,打印 "内部promise",由于链式了一个then,所以产生了一个微任务,当前微任务命名为 then2.
*当前微任务队列: [then2]
3、继续往下执行,遇到return , return是需要一个实际结果值,当前返回的是一个promise,执行同步的回调方法,打印 "内部promise2", 由于回调有一个链式then,这个then的排进微任务队列(暂且命名为 then4)
*当前微任务队列: [then2,then4]
按照2规则,return需要一个实际的值,它就会尝试从微任务队列中取出 then4执行得到 最终的结果返回。 那如此,取微任务队列的时候,按照 任务队列先进先出的逻辑,第一个就是[then2] 微任务,执行 [then2] 打印 "内部第一个then",由于then2的链式,又产生了微任务, 假命为了[then3],排进微任务队列。
** 当前微任务队列: [then4,then3]*
retuen未取到它想要的微任务,因为它需要的是then4的微任务执行结果,所以会再去微任务取。 当前在微任务队首的任务的是then4,取出来执行,由于 then4链式了一个then,假命为 [then5],
当前微任务队列: [then3,then5]。
为了给retuen 返回一个结果值,会再尝试从微任务队列中取出 [then5],按照 任务队列先进先出的逻辑,只能先取出 [then3] 执行,然后 打印"内部第二个then"。 再到 [then5],执行为 then5 打印 "内部第二个then2",返回最终结果给 reutrn。此时微任务队列空了。
4、继续往下执行,由于[then1]链接了一个then,此时又产生了一个微任务,假命为then6,
*当前微任务队列: [then6]
主线程代码再次完毕,去微任务队列检出 then6,代码执行,打印"外部第二个then"
至此结束,关键点在于promise什么时候去进微任务栈,此文章作为学习笔记记录,有问题可以评论区沟通。