记录一下手写PromiseAll
发表于:2025-11-18 | 分类: 前端
字数统计: 516 | 阅读时长: 2分钟 | 阅读量:

最近在面试时遇到了一个很经典的手写题,实现一个 Promise.all

(虽然经常听到 手写 Promise 手写 Promise.all 这种面试题,但是很惭愧一直没有深入了解 - -| 不晓得里面的很多细节问题,所以写的问题还是很大的。但是,俗话说的好,种一棵树最好的时间是十年前,其次就是现在 ^ ^
  1. 首先,Promise.all 用法都清楚,一般都是传入一个 Promise 数组,在 then 回调里拿到所有 Promise 的返回值数组,然后去使用。

  2. 很重要的一点是 Promise.all 最终返回的也是一个 Promise !!! 这点不要忘了

  3. 至于入参,经过了解知道它不一定是个数组,我们可以传入任意一种可迭代对象,比如 Set Map String Array 类型都都是可以的,所以入参进来后需要判断并统一处理

  4. 入参还有一种情况,是可迭代对象,但是长度为 0 ,这时需要直接 resolve 空数组

  5. 返回的这个 Promise 的执行结果,则取决于传入的所有 Promise 的执行结果,全部成功返回的 Promise 结果才会是 resolve,否则 reject

  6. 结合以上思路的需要注意的问题点,可以写出以下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    Promise.myAll = function (promises) {
    // 先校验参数是否为可迭代对象
    if (typeof promises[Symbol.iterator] !== 'function') {
    return new Promise((_, reject) => {
    reject(new TypeError(`${typeof promises} is not iterable (cannot read property Symbol(Symbol.iterator))`));
    });
    }
    let pmsArr = [...promises] // 先把可迭代对象转成数组,方便统一处理
    let results = []; // 存放每个 promise 执行结果
    let length = pmsArr.length;
    let didCount = 0;
    // 处理空数组:立即 resolve 空数组
    if (length === 0) {
    return Promise.resolve([]);
    }
    // 注意!!!是返回一个promise,而不是执行结果
    return new Promise((resolve, reject) => {
    for (let i = 0; i < pmsArr.length; i++) {
    Promise.resolve(pmsArr[i]).then(res => {
    results[i] = res;
    didCount++;
    // 执行完了再 resolve 结果数组
    if (didCount === length) {
    resolve(results);
    }
    }, err => {
    // 有一个失败就 reject
    reject(err);
    })
    }
    })
    }
上一篇:
部署项目常用命令与nginx配置
下一篇:
Cesium场景优化思路整理