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

递归JavaScript请求:请求间隔随时间逐渐变长问题排查

递归HTTP请求间隔逐次变大的原因与修复方案

问题根源分析

从代码结构和现象来看,间隔变大的核心原因有两个:

1. Promise反模式导致的异步嵌套延迟

addNewData函数使用了new Promise(async resolve => { ... })的错误写法——async函数本身会自动返回Promise,手动封装完全多余,还会引入额外的微任务队列调度延迟。每次递归调用时,这种不必要的Promise嵌套会让事件循环的调度成本逐次累积,最终表现为请求间隔变长。

2. 数据处理耗时随递归递增

虽然请求本身耗时没增加,但handleLogs操作的是全局Logs数组:随着递归次数增加,Logs长度越来越大,数据整理、操作的耗时会逐次变长。这部分耗时会被算在两次请求的间隔里(上一次请求完成后到下一次请求发起前的时间),导致开发者工具里看到的空白间隔逐渐变大。

另外,addContinousData作为async函数却没有await addNewData(),而是用.then()回调触发递归,这种回调嵌套会加剧微任务队列的堆积,进一步放大间隔延迟。

修复方案

1. 修复Promise反模式

直接利用async函数的特性,去掉手动封装的Promise:

async function addNewData() {
  try {
    await fetchData();
    handleLogs();
    return true;
  } catch (e) {
    // 可在此添加错误日志记录
    return false;
  }
}

2. 优化递归调用逻辑

改用await替代.then()回调,让异步流程更清晰,避免微任务堆积:

async function startContinousFetch() {
  continousFetch = true; // 控制全局开关
  await addContinousData();
}

async function addContinousData() {
  // 提前检查开关,避免无效操作
  if (!continousFetch) return;

  const resp = await addNewData();

  // 达到限制则停止
  if (LOGSLIMIT != null && Logs.length > LOGSLIMIT) {
    stopContinousFetch();
    return;
  }

  if (resp === false) {
    // 错误处理逻辑
  }

  // 继续递归
  if (continousFetch) {
    await addContinousData();
  }
}

3. 优化数据处理性能

重点排查handleLogs函数:

  • 当Logs达到LOGSLIMIT时,及时截断数组(比如直接截取最后N条),避免每次处理全量数据
  • 如果数据整理逻辑复杂,考虑采用增量处理(只处理新增数据),而非每次遍历整个数组

额外验证

修复后可以在开发者工具的Performance面板录制执行流程,查看每次递归中handleLogs的耗时变化,确认数据处理是否是间隔变大的主要诱因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 08:18:35