手写Promise.all、Promise.allSettled、Promise.finally、Promise.race

82 阅读1分钟

Promise.allSettled

Promise.prototype.allSettled = function (promises){
    let result = []
    let count = 0
    return new Promise((resolve) => {
        promises.forEach((promise, index) => {
            Promise.resolve(promise)
                .then(value => {
                    result[index] = {
                        value,
                        status: 'fulfilled'
                    }
                })
                .catch(reason => {
                    result[index] = {
                        reason,
                        status: 'rejected'
                    }
                })
                .finally(() => {
                    count++
                    if (count === promises.length){
                        resolve(result)
                    }
                })
        })
    })
}

Promise.all

function isPromise(promise){
    return (
        !!promise &&
        (typeof promise === 'object' || typeof promise === 'function') &&
        (typeof promise.then === 'function')
    )
}
Promise.prototype.all = function (promises) {
    if (!Array.isArray(promises)) return
    return new Promise((resolve, reject) => {
        let length = promises.length
        if (length === 0 ) new Promise.resolve(promises)
        let count = 0
        let result = new Array(length)
        for (let i = 0; i < length; i++){
            let promise = promises[i]
            if (isPromise(promise)){
                promise.then(res => {
                    count++
                    result[i] = res
                    if (count === length){
                        resolve(result)
                    }
                }).catch(err => {
                    reject(err)
                })
            } else {
                count++
                result[i] = promise
            }
        }
        if (count === length){
            resolve(result)
        }
    })

}

Promise.finally

Promise.prototype.finally = function (callback) {
    return this.then(
        value => Promise.resolve(callback()).then(() => value),
        reason => Promise.resolve(callback()).then(() => { throw reason })
    )
}

Promise.race

Promise.prototype.race = function (promises) {
    return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; i++){
            let promise = promises[i]
            if (isPromise(promise)){
                promise.then(resolve, reject)
            } else {
                resolve(promise)
            }
        }
    })
}