模拟实现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);
    }
);

执行结果:

相关推荐
黑土豆3 分钟前
在Vue3项目中实现PDF文件解析与预览的完整实践
前端·javascript·vue.js
han_8 分钟前
前端如何动态执行JavaScript代码?
前端·javascript
10年前端老司机3 小时前
10道js经典面试题助你找到好工作
前端·javascript
小小小小宇8 小时前
TS泛型笔记
前端
小小小小宇8 小时前
前端canvas手动实现复杂动画示例
前端
codingandsleeping8 小时前
重读《你不知道的JavaScript》(上)- 作用域和闭包
前端·javascript
小小小小宇8 小时前
前端PerformanceObserver使用
前端
zhangxingchao10 小时前
Flutter中的页面跳转
前端
烛阴10 小时前
Puppeteer入门指南:掌控浏览器,开启自动化新时代
前端·javascript
全宝11 小时前
🖲️一行代码实现鼠标换肤
前端·css·html