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