共计 1776 个字符,预计需要花费 5 分钟才能阅读完成。
起因
明天遇到一个题目,钻研了一天,从新复习了一遍 Promise 实现,得进去一个不算论断的论断 ……
这个题通过我的化简长成这样,求代码后果
const p = Promise.resolve()
new Promise(resolve => {new Promise(resolve => {resolve(p)})
.then(() => {console.log('after:await')
})
})
let p1 = p.then(() => {console.log('tick:a')
})
let p2 = p1.then(() => {console.log('tick:b')
})
let p3 = p2.then(() => {console.log('tick:c')
})
/*
p.then(() => {console.log('tick:a')
}).then(() => {console.log('tick:b')
}).then(() => {console.log('tick:c')
})
*/
promise 本质
咱们晓得 excutor 同步执行,then 外面的代码异步执行, 怎么实现的?
简略的说 (这里以胜利为例),then 外面的代码同步增加到 所属 promise
的胜利回调队列,当 excutor 外面的参数 resolve 办法执行的时候,会把胜利回调队列外面的代码顺次执行
对 resolve 参数的解决
如果 excutor 的 resolve 办法承受的参数是一个 Promise 对象会怎么样?
首先我在 promiseA+ 标准外面并没有找到这种状况的规定
而后我看了三个 promise 库,bluebird,es6-promise,promise, 都没有对这种状况作解决,也就是当成一个一般的对象
最初阮一峰的 es6 外面对这种状况有形容
resolve
函数的参数除了失常的值以外,还可能是另一个 Promise 实例, 这时p1
的状态就会传递给p2
,p2
的回调函数就会期待p1
的状态扭转
应该是新增加的 Promise 的规定
已有的材料的相干实现
在网上看了很多 Promise 实现,根本对 promise 的 excutor 的 resolve 办法的实现是这样的 promise 实现。对参数如果是 Promise 都是等 promise 执行完再调 resolve
constructor(executor){
...
let resolve = (value) =>{ // 如果 resolve 的值时一个 promise
if(value instanceof Promise){
// 我就让这个 promise 执行,把胜利的后果再次判断
return value.then(resolve,reject) // 参数会主动传递到 resolve 外面去
}
if (this.status === 'pending') {
this.status = 'fulfilled'
this.value = value
this.onFulfilledCallback.forEach(fn => fn(this.value))
}
}
...
留神,这种实现能跑过 PromiseA+ 标准测试用例!
从 A + 标准的角度没有问题
问题呈现
下面的实现相当于让咱们的题目中的 p 执行完后再 resolve,我转换一下题目局部,你们就很分明了
new Promise(resolve => {
new Promise(resolve => {//resolve(p)
// 相当于变成了
p.then(resolve)
})
.then(() => {console.log('after:await')
})
})
看起来很对,执行后果是
tick:a
after:await
tick:b
tick:c
然而咱们如果用原生 Promise, 理论执行后果是
tick:a
tick:b
after:await
tick:c
论断
貌似目前的 promise 在 resolve 参数解决上和 a + 标准上的不太一样
如果面试做题遇到的话, 求执行程序,如果参数是一个 Promsie 实例 i,我倡议这么解决。具体起因不晓得,晓得的大佬留言区通知我一声
var p = Promise.resolve()
new Promise(resolve => {
new Promise(resolve => {//resolve(p)
// 相当于变成了
p.then().then(resolve)
})
.then(() => {console.log('after:await')
})
})