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

使用Promise优化带Token缓存的API并发重复请求问题

并发重复请求Token问题优化

现有实现的核心问题

  • 首次触发时5-10个同id并发调用同时执行,此时缓存map无数据,所有请求都会独立发起Token获取接口调用,产生大量冗余请求
  • 原函数没有返回axios调用的Promise,调用方无法拿到异步请求的最终结果,逻辑本身存在缺陷

优化逻辑

  • 新增*Pending Promise(待完成请求Promise)*作为临时缓存,不只缓存最终Token结果
  • 同一id的首个请求发起后,立即把未完成的请求Promise存入缓存,后续同id的并发调用直接复用这个Pending Promise,不再重复发起接口请求
  • 等首个请求返回成功后,把缓存的Pending Promise替换为最终的Token响应结果;如果请求失败,立刻清空对应的Pending缓存,避免后续同id请求被永久卡住

优化后代码

// 沿用原有已全局定义的缓存map
export default (token, id) => {
  // 已存在最终缓存结果,直接返回token
  if (map[id] && !(map[id] instanceof Promise)) {
    return Promise.resolve(map[id]?.token);
  }

  // 已存在正在等待的同id请求,直接复用这个Promise,不重复发请求
  if (map[id] instanceof Promise) {
    return map[id];
  }

  // 首个发起的请求,构造请求Promise并存入缓存
  const requestTask = axios
    .post(
      `https://**********`,
      { id },
      {
        headers: {
          Authorization: `Bearer ${token}`
        }
      }
    )
    .then(response => {
      const cacheData = { ...response };
      // 请求成功后,把缓存从Pending Promise替换为实际响应数据
      map[id] = cacheData;
      return cacheData.token;
    })
    .catch(err => {
      // 请求失败清空Pending缓存,保证后续请求可以正常重试
      delete map[id];
      throw err;
    });

  // 把待完成的请求Promise存入缓存,供后续并发调用复用
  map[id] = requestTask;
  return requestTask;
};

优化效果

  • 同id的并发请求只会触发1次Token接口调用,所有并发触发的调用都会等待首次请求完成,直接复用最终返回的Token
  • 兼容原有缓存逻辑,已经拿到Token的id后续调用直接返回缓存值,不再发起请求
  • 增加了异常容错逻辑,请求失败后不会残留无效的Pending缓存,不会影响后续同id的请求重试

注:如果后续需要区分不同token、id组合的缓存,可以在map的key里拼接token和id的字符串,避免不同权限的请求复用同一份缓存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.02 00:24:03