You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript实现Promise.all时let results = [], i;语法的运行逻辑疑问

问题解答

1. let results = [], i;的语法作用

这是JavaScript支持的同作用域多变量合并声明语法,等价于分开写的两行声明:

let results = [];
let i;

这段声明的本意是初始化两个变量:

  • results:空数组,用来按输入顺序存储所有Promise的成功返回结果
  • i:循环下标计数器,用来标记当前遍历到可迭代对象的第几个元素

你单独运行这行代码得到i为undefined是正常的,因为这行没有给i赋初始值。

2. 这段代码本身存在多处错误,无法正常运行

你疑惑的逻辑问题确实存在,这段手写的Promise.all实现是有bug的:

  • 第一个问题就是i没有赋初始值0,第一次执行i++时会把undefined转成数字NaN,后续用NaN作为数组下标赋值完全不符合预期。
  • 第二个问题是异步回调的闭包引用错误:then回调是异步执行的,等回调触发时外层的for循环已经执行完毕,此时i已经等于可迭代对象的总长度,所有回调都会把结果存到同一个下标位置,没法保证结果顺序和输入顺序一致。作者本来写了let current = i;想通过块级作用域存储当前下标,但是回调里根本没有用到这个变量,属于代码疏漏。
  • 第三个问题是计数逻辑错误:代码里只在循环时给counter做递增,成功回调里没有做递减操作,counter === 0的判断永远不会成立,就算所有Promise都成功也不会触发resolve。

3. 修正后的可运行实现如下

function all(iterable){ 
  return new Promise(function(resolve, reject){ 
    let counter = 0;
    let results = [], i = 0; // 给下标计数器赋初始值0
    for(let p of iterable){
        const currentIndex = i; // 存储当前循环的下标,供异步回调使用
        counter++;
        Promise.resolve(p).then(function(res){ 
          results[currentIndex] = res; // 用当前循环的下标赋值,保证顺序
          counter--; // 每完成一个Promise就减1
          if(counter === 0) resolve(results) // 所有Promise都完成时返回结果
        }, reject);
       i++;
    }
    // 额外处理空输入的边界情况
    if(counter === 0) resolve(results);
  });
}

内容的提问来源于stack exchange,提问作者vaultsort.com

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 06:18:02