基于PromiseA规范手写的Promise

97 阅读2分钟
const PENDING = 'PENDING' // 等待状态
const FULFILLED = 'FULFILLED' // 成功状态
const REJECT = 'REJECT' // 失败状态
class Promise2 {
    constructor(exectuor) {
        this.onFulfilledCallbacks = [] // 存储成功的回调订阅者
        this.onRejectedCallbacks = [] // 存储失败的回调订阅者
        this.status = PENDING // 默认pending
        this.value = undefined // 成功的值
        this.reason = undefined // 失败的值
        const resolve = (value) => {
            if (this.status === PENDING) {
                this.status = FULFILLED // 成功状态
                this.value = value
                    // 发布
                this.onFulfilledCallbacks.forEach(fn => fn())
            }

        }
        const reject = (reason) => {
            if (this.status === PENDING) {
                this.status = REJECT // 失败状态
                this.reason = reason
                    // 发布
                this.onRejectedCallbacks.forEach(fn => fn())
            }

        }
        try {
            exectuor(resolve, reject)
        } catch (error) {
            reject(error)
        }
    }


    then(onFulfilled, onRejected) {
        /*
          如果 onFulfilled 不是一个函数
          且promise1已经fulfilled,
          则promise2必须以promise1的值fulfilled.(将传入的值返出去)
          如果 OnReject 不是一个函数
          且promise1已经rejected, 
          则promise2必须以相同的reason被拒绝.
        */
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

        // then 必须返回一个promise 
        let promise2 = new Promise2((resolve, reject) => {
            /*
              如果onFulfilled是一个函数:    
              它必须在promise fulfilled后调用, 且promise的value为其第一个参数。
              它不能在promise fulfilled前调用。
              不能被多次调用。
            */
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value)
                        this.promiseAnalyticalProcess(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                }, 0)
            }
            /*
             如果onRejected是一个函数,
             它必须在promise rejected后调用, 且promise的reason为其第一个参数。
             它不能在promise rejected前调用。
             不能被多次调用
            */
            if (this.status === REJECT) {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason)
                        this.promiseAnalyticalProcess(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                }, 0)
            }
            /*
              如果里面的代码在此同步进程中没有执行
              就将其放入一个函数,并存入数组中
            */
            if (this.status === PENDING) {
                this.onFulfilledCallbacks.push(() => {
                    try {
                        let x = onFulfilled(this.value)
                        this.promiseAnalyticalProcess(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
                this.onRejectedCallbacks.push(() => {
                    try {
                        // 如果onFulfilled 或 onRejected 返回了值x,
                        // 则执行Promise 解析流程[[Resolve]](promise2, x).
                        let x = onRejected(this.reason)
                        this.promiseAnalyticalProcess(promise2, x, resolve, reject)
                    } catch (error) {
                        // 如果onFulfilled 或 onRejected抛出了异常e, 
                        // 则promise2应当以e为reason被拒绝。
                        reject(error)
                    }
                })
            }
        })
        return promise2
    }
    catch (errorCallback) {
        return this.then(null, errorCallback)
    }
    promiseAnalyticalProcess(promise, x, resolve, reject) {
        // 如果promise 和 x 指向相同的值
        // 使用 TypeError做为原因将promise拒绝。
        if (promise === x) return reject(new TypeError('Chaining cycle detectedd for promise #<MyPromise>'))
            // resolve或reject有没有被调用过?
        let called = false
            // 如果x是一个对象或一个函数
        if (typeof x === 'object' && x !== null || typeof x === 'function') {
            try {
                let then = x.then
                if (typeof then === 'function') { // 是promise
                    then.call(x, (y) => {
                        // 多次调用resolve/reject只有第一次生效
                        if (called) return
                        called = true
                            // 解决new Promise里面多层嵌套new Promise的情况
                        promiseAnalyticalProcess(promise, y, resolve, reject)
                    }, (r) => {
                        if (called) return
                        called = true
                        reject(r)
                    })
                } else {
                    // 如果 then不是一个函数,则 以x为值fulfill promise。
                    resolve(x)
                }
            } catch (error) {
                if (called) return
                called = true
                reject(error)
            }
        } else {
            // 如果 x 不是对象也不是函数,则以x为值 fulfill promise。
            resolve(x)
        }

    }
}
module.exports = Promise2