手写Promise

69 阅读2分钟
/**
 * 构造函数:
 * 1.初始化数据,
 * 2.同步调用执行器函数
 * 2.内置函数resolve, reject修改实例状态,
 * 3.执行多个成功或失败的回调
 */
function Promise(executor) {
    const self = this;
    self.promiseState = 'pending'
    self.promiseResult = undefined;
    self.callbacks = [];

    function resolve(value) {
        if (self.promiseState !== 'pending') return;
        self.promiseState = 'fulfilled'
        self.promiseResult = value
        self.callbacks.forEach(callback => {
            queueMicrotask(() => {
                callback.onResolved(value)
            })
        })
    }

    function reject(reason) {
        if (self.promiseState !== 'pending') return
        self.promiseState = 'rejected'
        self.promiseResult = reason
        self.callbacks.forEach(callback => {
            queueMicrotask(() => {
                callback.onRejected(reason)
            })
        })
    }

    try {
        executor(resolve, reject)
    } catch(e) {
        reject(e)
    }
}
/**
 * then函数:
 * 1.指定默认回调函数
 * 2.返回promise实例
 * 3.异步执行成功或失败的回调函数
 * 4.存储多个回调函数,回调函数里放置修改状态的函数
 */
Promise.prototype.then = function(onResolved, onRejected) {
    const self = this
    if (typeof onResolved !== 'function') {
        onResolved = value => value
    }
    onResolved = typeof onResolved == 'function' ? onResolved : value => value;
    onRejected = typeof onRejected == 'function' ? onRejected : reason => {
        throw reason;
    }
    const newPromise = new Promise((resolve, reject) => {

        const fun = (callback) {
            queueMicrotask(() => {
                try {
                    const result = callback(self.promiseResult)
                    if (result == newPromise) {
                        reject(new TypeError('Chaining cycle detected'))
                        return;
                    }
                    if (result instanceof Promise) {
                        result.then(v => {
                            resolve(v)
                        }, r => {
                            reject(r)
                        })
                    } else {
                        resolve(result)
                    }
                } catch(e) {
                    reject(e)
                }
            })
        }
        if (this.promiseState === 'fulfilled') {
            fun(onResolved)
        }
    
        if (this.promiseState === 'rejected') {
            fun(onRejected)
        }
    
        if (this.promiseState === 'pending') {
            this.callbacks.push({
                onResolved() {
                    fun(onResolved)
                },
                onRejected() {
                    fun(onRejected)
                }
            })
        }
    })
    return newPromise;
}

/**
 * 
 * catch函数:
 * 1.与then函数少一个成功的回调函数
 */
Promise.prototype.catch = function(onRejected) {
    return this.then(null, onRejected)
}


/**
 * 
 * finally函数:
 * 1.执行回调函数,
 * 2.返回promise实例
 */
Promise.prototype.finally = function(onFinally) {
    return new Promise((resolve, reject) => {
        queueMicrotask(() => {
            const result = onFinally()
            if (result instanceof Promise) {
                result.then(resolve, reject)
            } else {
                resolve(result)
            }
        })
    })
}


/**
 * 
 * resolve函数:
 * 1.传入非promise类型的参数为成功
 * 2.如果为promise则当前的promise状态决定外部promise的状态
 */
Promise.resolve = function(value) {
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            value.then(resolve, reject)
        } else if (value && typeof value.then == 'function') {
            value.then(resolve, reject)
        } else {
            resolve(value)
        }
    })
}

/**
 * 
 * reject函数:
 * 1.传入拒绝原因
 * 2.返回一个promise对象
 */
Promise.reject = function(reason) {
    return new Promise((resolve, reject) => {
        return reject(reason)
    })
}

/**
 * all函数:
 * 1.当promises都成功后,返回成功的数组
 * 2.注意返回数组的顺序要按下标,才准确
 */
Promise.all = function(promises) {
    var result = new Array(promises)
    var count = 0
    if (promises.length == 0) {
        return [];
    }
    return new Promise((resolve, reject) => {
        promises.forEach((promise, i) => {
            if (promise instanceof Promise) {
                promise.then(v => {
                    result[i] = v
                    if (++count == promises.length) {
                        resolve(result)
                    }
                }, reject)
            } else {
                result[i] = promise
            }
        })
        
    })
}


/**
 * race函数:
 * 1.当promises那个先兑现就以哪个决定外部promise的状态
 */
Promise.race = function(promises) {
    return new Promise((resolve, reject) => {
        promises.forEach(promise => {
            if (promise instanceof Promise) {
                promise.then(resolve, reject)
            } else {
                resolve(promise)
            }
        })
    })
}

/**
 * allSettled函数:
 * 1.返回所有promise对应的状态和数据
 */
Promise.allSettled = function(promises) {
    const result = []
    const result_ = []
    return new Promise((resolve, reject) => {
        promises.forEach((promise, i) => {
            if (promise instanceof Promise) {
                promise.then(v => {
                    result[i] = {
                        status: 'fulfilled',
                        value: v
                    }
                    result_.push(v)
                    if (result_.length === promises.length) {
                        resolve(result)
                    }
                }, r => {
                    result[i] = {
                        status: 'rejected',
                        value: r
                    }
                    result_.push(r)
                    if (result_.length === promises.length) {
                        resolve(result)
                    }
                })
            } else {
                result[i] = {
                    status: 'fulfilled',
                    value: promise
                }
                result_.push(promise)
                if (result_.length === promises.length) {
                    resolve(result)
                }
            }
            
        })
    })
}

// any函数:
// 1.返回第一个成功的Promise状态,如果都reject,则报错
Promise.any = function(promises) {
    const result = []
    const result_ = []
    return new Promise((resolve, reject) => {
        promises.forEach((promise, i) => {
            if (promise instanceof Promise) {
                promise.then(v => {
                    resolve(v)
                }, r => {
                    result[i] = r
                    result_.push(r)
                    if (result_.length === promises.length) {
                        const error = new AggregateError(result, 'All promises were rejected')
                        reject(error)
                    }
                })
            } else {
                resolve(promise)
            }
        })
    })
}