手写一个符合promiseA规范的promise库

8次阅读

共计 4816 个字符,预计需要花费 13 分钟才能阅读完成。

promsie 使用及原理 / 手写一个符合 promise/A+ 规范的 promise

promise 使用及原理分析:

  • 通过 new 关键字创建 promise 实例, 接受一个 executor 参数, executor 方法返回两个方法 resolve, reject, 可用通过在 executor 方法中通过调用 resolve(使成功) 或调用 reject(使失败), 来控制 promise 状态
let p = new Promise((resolve, reject) => {resolve(100)
})
  • executor 中可以执行同步代码也可以执行异步代码
let p = new Promise((resolve, reject) => {setTimeout(() => {resolve(100)
    })
})
  • promise 原型对象上有 then 方法供 promise 实例调用, then 方法接受两个参数 onFulfilled, onRejected
  • onFulfilled 默认为一个函数 data => data
  • onRejected 默认为一个函数 err => {throw err}
  • 当 promise 状态为 fulfilled 时, 执行用户传入的 onFulfilled 方法
  • 当 promise 状态为 rejected 时, 执行用户传入的 onRected 方法
  • 当用户创建 promise 对象时采用异步, 那么执行 then 方法时没有调用 resolve 方法或 reject 方法, 所以 promise 状态依然为 pending 状态, 所以需要在 then 方法中采取发布订阅模式, 先保存 then 方法传来的 onFulfilled 和 onReje
  • 又因为同一个 promise 实例可以调用多次 then 方法, 从而传多个 onFulfilled 和 onRected, 所以发布订阅采用数组保存
  • onFulfilled 和 onRejected 方法中可能 throw Error, 所以在执行 onFulfilled 和 onRejected 时需要 try catch 捕获
  • then 方法返回一个新的 Promise 实现链式编程
  • 统一判断 then 方法传入的 onFulfilled 方法和 onRejected 方法中 return 的类型 (resolvePromise)
p.then(data => {console.log(data)
}, err => {console.log(err)
})
let p1 = p.then(data => {return p1   // 报类型错误})
p.then(data => {return new Promise((resolve, reject) => {resolve(100)
    })
})
  • catch 方法接受一个错误回调, 可以用 then 方法实现 (语法糖)
  • ES2018 中新增 finally 方法 也可以通过 then 方法实现 (语法糖) finally 要实现值得穿透, finally 前如果有 then 方法, 其返回值要穿过 finally 方法传给之后的 then
p.then(data => {return 100}).finally(() => {console.log('finally')
}).then(data => {console.log(data)  // 100
})
  • all, race 方法都接受一个 promise 数组
  • all 方法要所有 promise 都返回才 resolve 一个全部是成功态的数组, 只要有一个 rejected 就直接 reject
  • race 方法只要有一个 promise resolve 就直接 resolve

完整代码如下:

class Promise {constructor(executor) {
        this.status = Promise.PENDING
        this.value = undefined
        this.reason = undefined
        // 发布订阅的存储器 onResolvedCallbacks, onRejectedCallbacks
        this.onResolvedCallbacks = []
        this.onRejectedCallbacks = []
        this.initBind()
        this.init(executor)
    }
    initBind() {this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    init(executor) {
        // 防止 executor 中抛错
        try {executor(this.resolve, this.reject)
        } catch (e) {this.reject(e)
        }
    }
    resolve(data) {
        // 如果 resolve 中传入一个 promise, 那么返回改 promise 结果
        if (data instanceof Promise) data.then(this.resolve, this.reject)
        if (this.status === Promise.PENDING) {
            this.status = Promise.FULFILLED
            this.value = data
            this.onResolvedCallbacks.forEach(fn => fn())
        }
    }
    reject(reason) {if (this.status === Promise.PENDING) {
            this.status = Promise.REJECTED
            this.reason = reason
            this.onRejectedCallbacks.forEach(fn => fn())
        }
    }
    then(onFulfilled, onRejected) {const fulfilledHandle = (resolve, reject) => {
            // 此处用 setTimeout 异步才能拿到 promise2
            setTimeout(() => {
                try {let x = onFulfilled(this.value)
                    Promise.resolvePromise(promise2, x, resolve, reject)
                } catch (e) {reject(e)
                }
            })
        }
        const rejectHandle = (resolve, reject) => {setTimeout(() => {
                try {let x = onRejected(this.reason)
                    Promise.resolvePromise(promise2, x, resolve, reject)
                } catch (e) {reject(e)
                }
            })
        }
        // onFulfilled 和 onRejected 定义默认值
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
        onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}
        let promise2 = new Promise((resolve, reject) => {if (this.status === Promise.FULFILLED) {fulfilledHandle(resolve, reject)
            }
            if (this.status === Promise.REJECTED) {rejectHandle(resolve, reject)
            }
            if (this.status === Promise.PENDING) {this.onResolvedCallbacks.push(() => {fulfilledHandle(resolve, reject)
                })
                this.onRejectedCallbacks.push(() => {rejectHandle(resolve, reject)
                })
            }
        })
        // 返回一个新的 promise
        return promise2
    }
    catch (onRejected) {return this.then(null, onRejected)
    }
    static resolve() {return new Promise((resolve, reject) => {resolve()
        })
    }
    static reject() {return new Promise((resolve, reject) => {reject()
        })
    }
    finally(callback) {
        return this.then(data => Promise.resolve(callback()).then(() => data),
            err => Promise.resolve(callback()).then(() => {throw err})
        )
    }
    static all(promises) {return new Promise((resolve, reject) => {let result = []
            let count = 0
            const setResult = (key, value) => {result[key] = value
                if (++count === promises.length) {resolve(result)
                }
            }
            for (let i = 0; i < promises.length; i++) {let current = promises[i]
                if (Promise.isPromise(current)) {
                    current.then(data => {setResult(i, data)
                    }, reject)
                } else {setResult(i, current)
                }
            }
        })
    }
    static race(promises) {return new Promise((resolve, reject) => {for (let i = 0; i < promises.length; i++) {let current = promises[i]
                if (Promise.isPromise(current)) {current.then(resolve, reject)
                } else {resolve(current)
                }
            }
        })
    }
}
Promise.PENDING = 'pending'
Promise.FULFILLED = 'fulfilled'
Promise.REJECTED = 'rejected'
Promise.resolvePromise = (promise2, x, resolve, reject) => {
    // called 防止他人的 promise 即执行 resolve 又执行 reject
    let called
    if (promise2 === x) throw new TypeError('xxx')
    if (typeof x === 'function' || typeof x === 'object' && x !== null) {
        try {
            let then = x.then
            if (typeof then === 'function') {
                then.call(x, y => {if (called) return
                    called = true
                    // 递归解析, 总有一个结果 then 方法返回一个普通值
                    Promise.resolvePromise(promise2, y, resolve, reject)
                }, e => {if (called) return
                    called = true
                    reject(e)
                })
            } else {resolve(x)
            }
        } catch (e) {if (called) return
            called = true
            reject(e)
        }
    } else {resolve(x)
    }
}
Promise.isPromise = (obj) => {return typeof obj === 'function' || typeof obj === 'object' && obj !== null && obj.then && typeof obj.then === 'function'}
// 延迟对象
Promise.deferred = () => {const defer = {}
    defer.promise = new Promise((resolve, reject) => {
        defer.resolve = resolve
        defer.reject = reject
    })
    return defer
}

module.exports = Promise

正文完
 0