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

能否实现支持动态数组的有限并发Promise并行执行?

动态Promise并发控制实现方案

可行性结论

完全可以实现,这种需求属于带动态任务补充的并发限流场景,核心是维护任务池与待处理队列,在任务完成时自动补入新任务,无需依赖Promise.all或Promise.race的原生行为。

核心实现思路

  • 维护两个核心状态:
    • 待处理URL队列:存储待请求的URL,支持动态追加
    • 当前并发任务数:实时跟踪运行中的请求数量,确保不超过设定上限(100)
  • 实现任务启动器:当当前并发数小于上限且队列非空时,取出队列头部URL发起请求
  • 任务完成回调:每个请求结束(无论成功/失败)后,递减并发数,并再次触发任务启动逻辑,补入新任务
  • 动态URL处理:只要向待处理队列追加URL,任务启动器会自动检测并启动新任务,无需额外触发逻辑

代码示例

class ConcurrentFetcher {
  constructor(maxConcurrency = 100) {
    this.maxConcurrency = maxConcurrency;
    this.urlQueue = [];
    this.activeTasks = 0;
    this.results = [];
  }

  // 添加URL到队列,支持单个或批量添加
  addUrls(urls) {
    if (Array.isArray(urls)) {
      this.urlQueue.push(...urls);
    } else {
      this.urlQueue.push(urls);
    }
    // 添加后尝试启动新任务
    this._startTasks();
  }

  // 核心任务启动逻辑
  async _startTasks() {
    // 循环启动任务,直到达到并发上限或队列为空
    while (this.activeTasks < this.maxConcurrency && this.urlQueue.length > 0) {
      const url = this.urlQueue.shift();
      this.activeTasks++;
      this._handleFetch(url).finally(() => {
        this.activeTasks--;
        // 当前任务结束后,递归启动新任务
        this._startTasks();
      });
    }
  }

  // 单个URL的请求处理
  async _handleFetch(url) {
    try {
      const response = await fetch(url);
      const data = await response.json();
      this.results.push({ url, success: true, data });
      console.log(`完成请求: ${url}`);
    } catch (error) {
      this.results.push({ url, success: false, error: error.message });
      console.error(`请求失败: ${url}`, error.message);
    }
  }

  // 获取所有结果(适用于有限队列,无限队列可忽略此方法)
  async getResults() {
    // 等待所有活动任务和队列任务完成
    while (this.activeTasks > 0 || this.urlQueue.length > 0) {
      await new Promise(resolve => setTimeout(resolve, 100));
    }
    return this.results;
  }
}

// 使用示例
const fetcher = new ConcurrentFetcher(100);

// 初始添加215个URL
const initialUrls = Array.from({ length: 215 }, (_, i) => `https://example.com/api/item/${i}`);
fetcher.addUrls(initialUrls);

// 动态添加新URL(比如10秒后追加)
setTimeout(() => {
  const newUrls = Array.from({ length: 5 }, (_, i) => `https://example.com/api/new/${i}`);
  fetcher.addUrls(newUrls);
  console.log("已追加5个新URL");
}, 10000);

// 如果是有限队列,可在最后获取结果
// fetcher.getResults().then(results => {
//   console.log("所有请求完成", results);
// });

关键细节说明

  • 规避Promise.race缺陷:每个任务独立处理完成逻辑,不会中断其他运行中的任务,所有请求都会被完整执行
  • 动态队列适配:addUrls方法可随时调用,追加的URL会自动进入等待队列,在并发数有空位时启动
  • 错误隔离:单个请求失败不会影响其他任务执行,失败结果会被记录到results数组中
  • 无限队列支持:若URL队列是无限的,只需持续调用addUrls追加即可,控制器会一直维持最大并发数运行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 21:35:27