上文中主要说了一下 Promise
的简单运行,实现了 then
方法的调用以及多个 then
方法的处理,但是还没有做到如何在使用 then
的形式链式调用,也没有做错误处理,接来下本文就加上错误处理以及没有做的链式调用和 all
方法实现
废话不多数,接上文。
实现 then 方法的链式调用
首先如果要实现链式调用的话,就需要返回一个 Promise
对象,就像 JQ
那样链式的一样。思考一下,在 then
里面 return
一个返回值作为下一个 then
方法的参数。
then(resolve, reject) {
const p = new MyPromise((nextResolve, nextReject) => {
// 只有完成的状态才能使用 then
if (this.status === FULFILLED) {
// 获取到上一个promise成功回调执行的结果
const result = resolve(this.value)
resolvePromise(result, nextResolve, nextReject)
} else if (this.status === REJECTED) {
const result = reject(this.error)
resolvePromise(result, nextResolve, nextReject)
} else if (this.status === PENDING) {
// 这里要保存函数
this.onResolveCallbacks.push(() => {
const result = resolve(this.value);
resolvePromise(result, nextResolve, nextReject)
})
this.onRejectCallbacks.push(() => {
const result = reject(this.error)
resolvePromise(result, nextResolve, nextReject)
})
}
})
return p
}
// 统一处理
function resolvePromise(result, nextResolve, nextReject) {
// 判断执行的结果是否是一个promise对象
if (result instanceof MyPromise) {
result.then(nextResolve, nextReject);
} else {
// 将上一个promise成功回调执行的结果传递给下一个promise成功的回调
nextResolve(result);
}
}
实现一下 all 方法
all
方法的特点就是传入一个数组且数组内的元素都是一个个 Promise
对象,如果成功就按数字顺序打印出来,其中一个失败则直接返回错误。
这里要注意下 按顺序执行打印,如果使用原生 JavaScript 要怎么去实现这个方法呢?思考一下?
all(arr) {
return new MyPromise((resolve, reject) => {
let list = []
let count = 0
// for 循环去执行 promise
for (let i = 0; i < arr.length; i++) {
arr[i].then((value) =>{
// 把执行的结果保存到新的数组中
list.push(value)
// 保存之后再让 count + 1
count++
// 当 count 的数量刚好和 arr 的数量相等时,通过 resolve 返回新的数组
if (count === arr.length) {
resolve(list)
}
},(error) => {
// 其中一个有错误就 reject 出来
reject(error)
})
}
})
}
像这样 all 的方法就实现了。
总结
如果认真的通篇看下来,实现 Promise 其实不算难的,难就难在整体的思路以及各方法直接调用的处理,顶多来说就是不停的设置回调,最复杂的地方也就是链式处理,说白了就是 return 出的 MyPromise 然后在调用将上一个 Promise 成功回调执行的结果传递给下一个 Promise 成功的回调,如此便实现了传递效果。
本文参考以下下文章:
从一道让我失眠的 Promise 面试题开始,深入分析 Promise 实现细节