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

执行结果:

相关推荐
shoubepatien5 分钟前
JavaWeb_Web基础
java·开发语言·前端·数据库·intellij-idea
WordPress学习笔记13 分钟前
wordpress外贸主题Google地图添加(替换)方案
前端·wordpress·wordpress地图
码农秋1 小时前
Element Plus DatePicker 日期少一天问题:时区解析陷阱与解决方案
前端·vue.js·elementui·dayjs
未来之窗软件服务1 小时前
未来之窗昭和仙君(五十六)页面_预览模式——东方仙盟筑基期
前端·仙盟创梦ide·东方仙盟·昭和仙君·东方仙盟架构
top_designer1 小时前
Illustrato:钢笔工具“退休”了?Text to Vector 零基础矢量生成流
前端·ui·aigc·交互·ux·设计师·平面设计
星哥说事1 小时前
星哥带你玩飞牛NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手!
前端
donecoding1 小时前
前端AI开发:为什么选择SSE,它与分块传输编码有何不同?axios能处理SSE吗?
前端·人工智能
安_1 小时前
<style scoped>跟<style>有什么区别
前端·vue
姝然_95271 小时前
Claude Code 命令完整文档
前端
wjcroom1 小时前
web版进销存的设计到实现一
前端