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

TypeScript中带并发控制的批量Promise执行及类型优化问题

给mapConcurrent添加TypeScript强类型支持

你遇到的问题是原函数用了any类型导致类型信息丢失,我们可以通过TypeScript泛型让这个函数具备完整的类型推导能力,完美适配你需要的Promise返回类型。

类型化改造后的完整代码

function mapConcurrent<T, U>(
  items: Array<T>,
  maxConcurrent: number,
  fn: (item: T, index: number) => Promise<U>
): Promise<Array<U>> {
  let index = 0;
  let inFlightCntr = 0;
  let doneCntr = 0;
  const results = new Array<U>(items.length);
  let stop = false;

  return new Promise((resolve, reject) => {
    const runNext = () => {
      const i = index;
      inFlightCntr++;
      fn(items[index], index++)
        .then((val: U) => {
          doneCntr++;
          inFlightCntr--;
          results[i] = val;
          run();
        })
        .catch((err) => {
          stop = true;
          reject(err);
        });
    };

    const run = () => {
      while (!stop && inFlightCntr < maxConcurrent && index < items.length) {
        runNext();
      }
      if (doneCntr === items.length) {
        resolve(results);
      }
    };

    run();
  });
}

关键类型说明

  • 泛型T:代表输入数组items中每个元素的类型
  • 泛型U:代表异步处理函数fn返回的Promise的结果类型
  • 函数返回值Promise<Array<U>>:自动推导为所有Promise结果组成的数组类型,完全和你的业务类型绑定

使用示例

比如你有一个返回Promise<{id: string}>的处理函数,用改造后的mapConcurrent会自动推断结果数组类型为Array<{id: string}>:

// 示例异步函数:返回包含id的对象
const fetchItem = (id: number): Promise<{id: string}> => {
  return Promise.resolve({ id: id.toString() });
};

// 输入数组
const itemIds = [1, 2, 3, 4, 5];

// 并发数设为3执行
mapConcurrent(itemIds, 3, fetchItem)
  .then(results => {
    // results的类型自动推断为 Array<{id: string}>
    console.log(results); // [{id: "1"}, {id: "2"}, ...]
  })
  .catch(err => {
    console.error(err);
  });

额外说明

  • 不需要手动指定泛型参数,TypeScript会根据你传入的items和fn自动推导出T和U的类型
  • 原有的并发控制逻辑完全保留,错误处理(只要有一个Promise reject就立即终止并reject)也和之前一致
  • 如果后续想尝试第三方库,p-limit是个不错的选择,它对TypeScript支持非常友好,用法也很简洁:
    import pLimit from 'p-limit';
    
    const limit = pLimit(3);
    const promises = itemIds.map(id => limit(() => fetchItem(id)));
    Promise.all(promises).then(results => { /* ... */ });
    

内容的提问来源于stack exchange,提问作者Benjamin Bohec

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 00:37:29