手写promise.all

156 阅读1分钟

promise.all

 入参: 是一个promise的iterable,就是参数是可以被for...of的迭代器,可以迭代的,有Array,Map, Set

出参:一个Promise实例,入参中有一个promise为rejected状态,则promise.all直接rejected第一个错误信息,但是,入参中的其他promise还是会各自执行到Fulfillment/Rejection的状态。

/**
 * @desc 手写一个Promise.all
 * @param Iterable list 一个promise的迭代器
 * @return promise 一个promise实例
 */
function all(list) {
    // 首先返回一个promise实例
    return new Promise((resolve, reject) => {
        // 判断入参是否为一个可迭代对象(目前,我也不知道怎么判断,就判断是否是一个数组)
        if(!Array.isArray(list)) {
            return reject("argument is not iterable")
        }
        // 定义的迭代器,来存放数据(这里以处理Array为栗子)
        const arr = [];
        // 定义一个计数器,来统计迭代对象中的有多少Promise处理完成
        let count = 0;
        // Array Set Map都有forEach方法遍历
        list.forEach((v, i) => {
            // 使用Promise.resolve的静态方法将入参中的每一项变成一个Promise
            Promise.resolve(v)
            .then(res => {
                // 将入参中promise放回的结果放到对应的result对应的位置上
                result[i] = res;
                // 判断是否所有promise都完成,不能使用result.length === list.length
                // 因为数据的length值,是根据数组最后一个数据的下标来决定的
                if(++count === list.length) {
                    // 如果所有promise都处理完成,则返回result
                    resolve(result)
                }
            })
            .catch(err => {
                reject(err);
            })
        })
    })
}

注意点:

const arr = [];
arr[3] = 111;
arr.length === 4  // true

JavaScript 数组length的返回值,是根据最后一个元素所在的下标决定的