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

如何优雅处理JS fetchData函数并发调用重复请求问题?

解决fetchData并发重复请求的优雅方案

核心优化思路

把处于pending状态的请求Promise缓存起来,而非仅缓存最终响应数据。这样并发调用时,后续请求直接复用这个pending的Promise,无需重复发起网络请求。

优化后的代码

function fetchData() {
  // 已有缓存数据,直接返回已resolve的Promise
  if (window.data) {
    return Promise.resolve(window.data);
  }
  // 已有正在进行的请求Promise,直接复用
  if (window.pendingDataPromise) {
    return window.pendingDataPromise;
  }
  // 发起新请求,先缓存pending的Promise
  const requestPromise = fetch('http://example.com/data.js')
    .then(response => response.json())
    .then(json => {
      window.data = json;
      // 请求完成后清除pending标记(可选,按需调整)
      delete window.pendingDataPromise;
      return json;
    })
    .catch(error => {
      // 请求失败也要清除pending标记,避免后续复用失败的Promise
      delete window.pendingDataPromise;
      throw error;
    });

  window.pendingDataPromise = requestPromise;
  return requestPromise;
}

方案说明

  • 第一个调用发起请求时,会将请求的Promise存入window.pendingDataPromise,后续并发调用直接返回这个Promise,等待同一请求完成。
  • 请求成功后,将数据存入window.data,同时删除pendingDataPromise(若业务允许后续清空window.data后重新请求,此步骤必不可少)。
  • 增加错误处理:请求失败时清除pendingDataPromise,防止后续调用一直拿到失败的Promise。

替代方案(Promise不可行时)

若因限制无法使用Promise,可采用自定义事件+回调队列的方式:

function fetchData(callback) {
  if (window.data) {
    callback(null, window.data);
    return;
  }
  // 已有请求在进行,将回调加入队列
  if (window.dataRequestCallbacks) {
    window.dataRequestCallbacks.push(callback);
    return;
  }
  // 初始化回调队列
  window.dataRequestCallbacks = [callback];
  
  fetch('http://example.com/data.js')
    .then(res => res.json())
    .then(json => {
      window.data = json;
      // 通知所有等待的回调
      window.dataRequestCallbacks.forEach(cb => cb(null, json));
      delete window.dataRequestCallbacks;
    })
    .catch(err => {
      window.dataRequestCallbacks.forEach(cb => cb(err));
      delete window.dataRequestCallbacks;
    });
}

但该方式需基于回调编写代码,可读性与维护性不如Promise方案,仅作为特殊场景下的备选。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 00:01:05