resolve1(arg){
if(arg.tyeof === promise){
weirenwu(()=>{
arg.then(()=>{ //该箭头函数为then方法的参数,即回调函数,调用参数arg的then方法,arg为promise,then方法内部处理机制按照then方法内部源码进行处理
resolve1()//then方法中会执行外层promise的resolve1方法,而不是arg中的promise的resolve方法,相当于递归。
//从而改变外层promise的状态,同时如果有_fulfilledQueues的话还会在微任务中执行_fulfilledQueues中的回调函数
})
},0)
return
}
status = 1//如果参数不是promies,那么会先将外层promise的状态设置为1,即resolve状态,然后再判断有没有_fulfilledQueues,例子1可以证明
if(_fulfilledQueues){ //如果参数不是promise,那么判断是否存有then方法的回调函数
weirenwu(()=>{
//遍历_fulfilledQueues,并执行_fulfilledQueues中储存的then方法的回调函数
},0)
}
}
then1(){
return new Promise( (resolve1)=>{
if(pending){ //父级promise即调用then方法的那个promise的状态是pending的话
//把then方法中的回调函数(记做cb1)放入到_fulfilledQueues
//then方法返回的这个new Promies的状态是由cb1执行的时候改变的,resolve1会作为参数传递给cb1,只有在cb1执行的时候才会调用resolve1,才会将then方法返回的这个new Promies的状态由pending状态改为resolve
//从resolve方法中我们可以分析到只有在执行微任务的时候才会进行 _fulfilledQueues的遍历以及存在于_fulfilledQueues中的cb1的执行
//所以此时在执行宏任务中遇到的then方法,其状态是pending
}else{
weirenwu(()=>{
//执行then方法中传递的回调函数,微任务执行的时候才会改变return的promise的状态
},0)
}
} )
//通过上述分析可以知道,在宏任务中调用then方法时,then方法返回的promise都是pending状态,这保证 了then后继续链式调用then时,后一个then中的回调函数不会立马执行,会先放入到前一个then返回的promise的_fulfilledQueues中,
//只能等前边的then返回的promise执行了resolve之后(resolve的时候会判断是否有_fulfilledQueues,有的话再放入微任务中执行),才会执行后边then中的回调函数。
}
例子1:
let a = new Promise((resolve)=>{
setTimeout(()=>{
new Promise((resolve)=>{
resolve()
}).then(()=>{console.log('a',a)})//resolve
resolve()
console.log('c',a)//resolve
},0)
})
console.log('p',a)//pending
a.then(()=>{console.log(1111,a)})//resolve
==========================================
结论:
resolve接收promise作为参数时,通过arg.then可看出只有参数promose的状态改变为完成时,才会去调用then中的回调函数,该回调函数中才会去执行外层promise的resolve方法,从而来改变外层promise的状态,同时如果外层promise中有_fulfilledQueues(注释1)的话,会放入微任务中执行遍历_fulfilledQueues执行其中储存的回调函数。
如此从内往外一层层执行,只有内部的promise状态改变才会去触发外部promise的状态改变,当内部promise状态没有改变时,外部的promise状态也不会改变。
注释1:
_fulfilledQueues内部存的是外层promise为pending时将then中的回调函数(由于执行resolve时会先 status=1,后判断有没有_fulfilledQueues,如果有的话又是在下一个微任务中执行,所以执行_fulfilledQueues中的回调函数时,打印出的外层的promise的状态已经是resolve的)
_fulfilledQueues中存储的回调函数 不仅有我们自己在代码中通过这种promise.then(()=>{})写法写的then中的箭头函数,而且也可能有内部代码中的arg.then(()=>{})中的箭头函数,如下例2:promise2内部接收一个promose1作为resolve的参数,同时又作为了外层promise3的resolve的参数,第一次执行script标签整体代码时即第一个宏任务时,promise2肯定是pending状态,
那么执行resolve3()执行的时候,通过resolve内部代码实现看到arg.then(()=>{})这段代码中的arg是promise2,promise2又是pending状态,那么就会把arg.then(()=>{})中的箭头函数放入到promise2的_fulfilledQueues中,这也能够保证当promise2的resolve被执行的时候,先是把promise2的状态设置为1,
然后_fulfilledQueues中有arg.then(()=>{})中的箭头函数,所以会放在微任务队列中在微任务队列中执行该箭头函数,我们知道该箭头函数中存放的是resolve3(),所以执行resolve3时改变promise3的状态和执行promise3的_fulfilledQueues。_fulfilledQueues中存放arg.then(()=>{})中的箭头函数这一做法 保证了里层promise执行resolve的时候能够通过执行_fulfilledQueues中存放的arg.then(()=>{})中的箭头函数来触发外层promise的resolve。
例子2:let a = new Promise3((resolve3)=>{resolve3(
new Promise2((resolve2)=>{resolve2(
new Promise1((resolve1)=>{resolve1(
)})
)})
)})
a.then(()=>{console.log(777,a)})
例子3:
promise11: new Promise((resolve4)=>{resolve4(
new Promise((resolve3)=>{resolve3(
new Promise((resolve2)=>{resolve2(
new Promise((resolve1)=>{resolve1(
new Promise((resolve)=>{resolve()})
)})
)}).then(()=>{console.log(1)})
)})
)})
promise22: new Promise((resolve4)=>{resolve4(
new Promise((resolve3)=>{resolve3(
new Promise((resolve2)=>{resolve2(
new Promise((resolve1)=>{resolve1(
new Promise((resolve)=>{resolve()})
)}).then(()=>{console.log(2)})
)})
)})
)})
执行顺序2,1
根据以上原理可以知道嵌套的promise是由内往外执行从而改变外层promise的状态的,两个层层嵌套的promise比较顺序时, script第一次宏任务时会找出两个promise中的微任务放入微任务队列,执行微任务时,每执行一次微任务会产生一个新的微任务,将新的微任务放入到微任务队列的尾部,
所以两个嵌套的promise,谁的then方法嵌套的越靠里谁就会先执行,如果两个then位置一样,那就看这两个的promise(promise11与promise22)在同步代码中的位置,谁在谁就先执行,因为谁在前谁就会先放入到微任务队列。
Promise.resolve()中接收一个Promise作为参数时会立马原封不动的返回该Promise,会立马返回,不会再在微任务中返回该Promise,所以Promise.resolve().then(()=>{console.log(1)})与new Promise(()=>{resolve()}).then(()=>{console.log(2)})这两个是谁在前谁先执行