模拟实现Promise.all

模拟实现Promise.all

一、前言

Promise.all 是es2015的Promise内置的一个静态方法,接受一个promises 数组,返回一个新的promise:

  1. 如果promises 数组的每一项的状态都变为fulfilled ,将返回的每一个promise 的结果按照原来数组的顺序,封装为一个新的数组作为成功的结果。
  2. 如果其中一个promise 的状态变为rejected, 就返回该promise

二、准备测试数据

javascript 复制代码
const promisesSuccess = []; // 五个成功的promise 数组
const promises = []; // 随机的promise
​
for (let i = 0; i < 5; i++) {
    // 成功的promise
    promisesSuccess.push(
        new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(`${i * 1000}--resolve`);
            }, i * 1000);
        })
    );
    // 随机promise
    Math.random() > 0.1
        ? promises.push(
            new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(`${i * 1000}--resolve`);
                }, i * 1000);
            })
        )
        : promises.push(
            new Promise((resolve, reject) => {
                setTimeout(() => {
                    reject(`${i * 1000}--reject`);
                }, i * 1000);
            })
        );
}

三、实现Promise.all

1. 乞丐版:

javascript 复制代码
Promise.myAll = (promises) => {
    const arr = [];
    return new Promise((resolve, reject) => {
        promises.forEach((item, index) => {
            Promise.resolve(item).then((res) => {
                arr.push(res);
                if (arr.length === promises.length) resolve(arr);
            }, (reason)=>{
                reject(reason)
            });
        });
    });
};

乞丐版存在的问题:

  1. 返回的数组没有按照原本的顺序,而是按照peomise 完成的顺序加入数组
  2. 错误可以简写。

注意: 如果不额外定义一个length ,代码如下:

ini 复制代码
Promise.myAll = (promiseArr) => {
    const arr = [];
    return new Promise((resolve, reject) => {
        promises.forEach((item, index) => {
            Promise.resolve(item).then((res) => {
                arr[index] = res;
                if (arr.length === promises.length) resolve(arr);
            }, reject);
        });
    });
};

分析: 如果promiseArr 数组的 的最后一项先完成,此时的arr为[empty,empty,...,empty, res],显然此时的arr.length === promiseArr.length 成立,导致出错。

2. 完整版

ini 复制代码
Promise.myAll = (promiseArr) => {
    const arr = [];
    let count = 0;
    return new Promise((resolve, reject) => {
        promises.forEach((item, index) => {
            Promise.resolve(item).then((res) => {
                arr[index] = res;
                count += 1; 
                if (count === promises.length) resolve(arr);
            }, reject);
        });
    });
};

四、 测试

javascript 复制代码
Promise.myAll(promisesSuccess).then(
    (res) => {
        console.log(res);
    },
    (reason) => {
        console.log(reason);
    }
);
​
Promise.myAll(promises).then(
    (res) => {
        console.log(res);
    },
    (reason) => {
        console.log(reason);
    }
);

执行结果:

相关推荐
木子雨廷6 分钟前
Flutter 开发一个plugin
前端·flutter
重生之我是一名前端程序员8 分钟前
websocket + xterm 前端实现网页版终端
前端·websocket
sorryhc10 分钟前
【AI解读源码系列】ant design mobile——Space间距
前端·javascript·react.js
uhakadotcom24 分钟前
NPM与NPX的区别是什么?
前端·面试·github
GAMC34 分钟前
如何修改node_modules的组件不被install替换?可以使用patch-package
前端
页面仔Dony35 分钟前
webpack 与 Vite 深度对比
前端·前端工程化
Juchecar40 分钟前
Vue3 组件生命周期详解
前端·vue.js
页面仔Dony42 分钟前
打包工具配置base、publicPath字段的作用和区别
前端·前端工程化
gongzemin44 分钟前
前端下载xlsx 提示试图打开文件时遇到错误
前端
我是ed1 小时前
# JS获取用户访问网页的浏览器、IP、地址等信息 实现访问统计
前端