Skip to content

Promise

js
Promise.myResolve = function (value) {
    // 是Promise实例,直接返回即可
    if (value && typeof value === 'object' && (value instanceof Promise)) {
        return value
    }
    // 否则其他情况一律再通过Promise包装一下
    return new Promise((resolve) => {
        resolve(value)
    })
}

Promise.myReject = function (value) {
    return new Promise((_, reject) => {
        reject(value)
    })
}

/**
 * 最终p的状态由p1、p2、p3决定,分成两种情况。
 * (1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
 * (2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
 *
 * @param promises
 * @returns {Promise<unknown>}
 */
Promise.myAll = function (promises) {
    return new Promise((resolve, reject) => {
        let count = 0;
        let result = []

        if (promises.length === 0) return resolve([]);

        promises.forEach(promise => {
            promise.resolve(promise).then((res) => {
                count += 1;
                result[i] = res;
                if (count === promise.length) {
                    resolve(result)
                }
            }).catch(err)
        })
    })
}

/**
 * Promise.allSettled()方法接受一个数组作为参数,数组的每个成员都是一个 Promise 对象,并返回一个新的 Promise 对象。
 * 只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更,一旦发生状态变更,
 * 状态总是fulfilled,不会变成rejected
 *
 * @param promises
 * @returns {Promise<unknown>}
 */
Promise.myAllSettled = (promises) => {
    return new Promise((rs, rj) => {
        let count = 0
        let result = []
        const len = promises.length
        // 数组是空的话,直接返回空数据
        if (len === 0) {
            return rs([])
        }

        promises.forEach((p, i) => {
            Promise.resolve(p).then((res) => {
                count += 1
                // 成功属性设置
                result[ i ] = {
                    status: 'fulfilled',
                    value: res
                }

                if (count === len) {
                    rs(result)
                }
            }).catch((err) => {
                count += 1
                // 失败属性设置
                result[i] = {
                    status: 'rejected',
                    reason: err
                }

                if (count === len) {
                    rs(result)
                }
            })
        })
    })
}

/**
 * Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
 * 只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数
 * @param promises
 * @returns {Promise<unknown>}
 */
Promise.myRace = (promises) => {
    return new Promise((rs, rj) => {
        promises.forEach((p) => {
            // 对p进行一次包装,防止非Promise对象
            // 并且对齐进行监听,将我们自己返回的Promise的resolve,reject传递给p,哪个先改变状态,我们返回的Promise也将会是什么状态
            Promise.resolve(p).then(rs).catch(rj)
        })
    })
}