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

实现限并发请求队列时陷入无限循环,求问题排查与解决

问题分析与修复方案

核心问题:同步循环与异步操作的执行时机冲突

你的while循环是同步执行的,但fetchMock返回的Promise属于异步操作。执行流程中出现了致命矛盾:

  1. 第一次循环时,你取出前3个endpoint,把limit同步减到0,此时endpoints剩余[4,5]。
  2. 同步的while会持续检查endpoints.length > 0(条件一直成立),但此时limit已经是0,代码卡在while里无限空转,根本不会给异步操作的finally回调执行的机会,最终导致内存耗尽崩溃。
  3. 即便异步操作能执行,原逻辑里的limit++也无法被同步循环感知,因为循环已经进入死循环状态。

修复后的代码

下面的方案通过维护活跃请求计数器+递归补位的方式,实现“一个请求完成后立即发起下一个”的并发控制:

const requestQueue = (endpoints, callback, limit = 3) => {
  // 复制原数组,避免修改外部传入的数据源
  const queue = [...endpoints];
  let activeRequests = 0;

  const runNext = () => {
    // 队列空了就终止递归
    if (queue.length === 0) return;
    // 还有可用并发名额时发起请求
    if (activeRequests < limit) {
      activeRequests++;
      const endpoint = queue.shift();
      fetchMock(endpoint)
        .then(data => callback(data))
        .catch(err => callback(err))
        .finally(() => {
          activeRequests--;
          // 当前请求完成后,立刻启动下一个
          runNext();
        });
    }
  };

  // 初始化启动最多limit个请求
  for (let i = 0; i < limit; i++) {
    runNext();
  }
};

function fetchMock(endpoint) {
  // 模拟真实接口的延迟,更直观看到并发控制效果
  return new Promise(resolve => {
    setTimeout(() => resolve(endpoint), 1000);
  });
}

requestQueue([1,2,3,4,5], data => console.log(data));

修复逻辑说明

  • 用activeRequests跟踪当前正在运行的请求数,避免修改原limit参数导致的逻辑混乱
  • 每次请求完成后(finally回调),先减少活跃请求数,再递归调用runNext自动补位下一个请求
  • 初始阶段先启动最多limit个请求,之后保持并发数稳定在设定值
  • 复制原数组作为队列,避免修改外部传入的数据源产生副作用

内容的提问来源于stack exchange,提问作者j-0-n-e-z

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 02:51:12