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

基于Axios的Promise递归重试请求问题咨询

问题诊断与修复方案

你的代码存在几个核心问题,直接导致了请求慢、很少返回结果的现象:

1. 没给axios设置超时时间

axios默认不会主动触发超时,如果你没在请求配置里加timeout参数,e.message === GET_IPFS_TIMED_OUT这个判断根本不会生效——所谓的“超时重试”完全没起作用。一旦IPFS网关响应缓慢,axios会一直挂着等待,永远进不了catch分支,这就是函数“很少返回”的主要原因。

2. 无限递归重试无限制

就算超时判断生效了,当前代码会在超时后无限调用getIPFSMedia,没有重试次数上限。要是遇到持续超时的情况,Promise链会一直挂着,甚至可能触发栈溢出,永远拿不到结果。

3. 错误处理有漏洞

遇到非超时错误时,catch分支只打印日志却没返回rejected的Promise,这会让getIPFSMedia在错误场景下返回一个resolved状态的Promise,值是undefined,上层await拿到undefined也无法感知错误。


修复后的代码

// 配置重试上限和超时时间
const MAX_RETRIES = 3;
const REQUEST_TIMEOUT = 5000; // 5秒超时
const GET_IPFS_TIMED_OUT = `timeout of ${REQUEST_TIMEOUT}ms exceeded`;

const getIPFSMedia = async (url, retryCount = 0) => {
  try {
    const response = await axios.get(url, {
      responseType: 'blob',
      timeout: REQUEST_TIMEOUT // 强制设置超时
    });
    return URL.createObjectURL(response.data);
  } catch (e) {
    // 仅在超时且还有重试次数时重试
    if (e.message === GET_IPFS_TIMED_OUT && retryCount < MAX_RETRIES) {
      console.log(`请求超时,第${retryCount + 1}次重试...`);
      return getIPFSMedia(url, retryCount + 1);
    } else {
      console.error("获取IPFS文件失败:", e.message);
      // 抛出错误让上层捕获,避免静默失败
      throw e;
    }
  }
};

const fetchData = async () => {
  try {
    const image = await getIPFSMedia(url);
    console.log(image);
    // 这里可以处理拿到的文件链接
  } catch (e) {
    // 处理最终失败的情况
    console.error("最终获取失败:", e);
  }
};

改进点说明

  • 强制设置超时:给axios加timeout参数,确保超时后能触发重试逻辑,不会无限等待。
  • 限制重试次数:通过retryCount控制最多重试3次,避免无限递归导致的Promise挂起。
  • 完善错误处理:非超时错误或重试耗尽时主动抛出错误,让上层能捕获并处理,不会出现“没返回结果”的静默失败。
  • 改用async/await:比链式then/catch更直观,容易跟踪重试状态,逻辑更清晰。

另外,你提到直接打开链接能立即获取文件,可能是浏览器对IPFS链接做了缓存,而axios请求默认没带缓存相关头,可以试试在请求配置里加headers: { 'Cache-Control': 'no-cache' },或者检查是不是用了不同的IPFS网关(比如浏览器用本地节点,axios用公共网关)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 15:15:34