关于 fetch,几个常被问到的问题

举报
柠檬-夏日清爽 发表于 2026/10/02 10:51:28 2026/10/02
【摘要】 整理 fetch 使用中的四个常见问题——用 AbortSignal.timeout 设超时、AbortController 取消请求、keepalive 保证页面关闭时的上报、以及重试要区分 5xx 与 4xx 并做指数退避。

用 fetch 发请求很简单,但真到业务里,超时、取消、重试这些一个都躲不掉。整理几个经常被问到的点。

怎么给 fetch 设超时?

早年的写法是 setTimeout 配 AbortController,到点手动 abort。现在简单些:

const res = await fetch(url, { signal: AbortSignal.timeout(5000) });

AbortSignal.timeout 生成一个五秒后自动中止的信号,超时会抛 TimeoutError。想自己控制时机就用 AbortController,两者不冲突。

怎么取消一个已经发出的请求?

const ctrl = new AbortController();
fetch(url, { signal: ctrl.signal });
ctrl.abort();

调用 abort() 之后请求会被中断,fetch 的 Promise 以 AbortError 拒绝。页面切换、组件卸载时记得调,不然请求还在飞,回来可能把旧数据盖到新页面上。

keepalive 是干嘛的?

navigator.sendBeacon(url, data);
fetch(url, { method: 'POST', body: data, keepalive: true });

页面即将关闭时,普通的 fetch 会被浏览器掐掉,埋点上不去。keepalive: true 告诉浏览器让这个请求活过页面卸载。它有体积上限(一般 64KB),超了会失败,所以只适合小数据上报。

失败要自动重试吗?

要看是什么错。网络抖动、503 这类可以重试;400、401、422 这类是请求本身有问题,重试一百次也一样。

async function fetchWithRetry(url, opts = {}, times = 2) {
  for (let i = 0; i <= times; i++) {
    try {
      const res = await fetch(url, opts);
      if (res.status < 500) return res;
      if (i === times) return res;
    } catch (e) {
      if (i === times) throw e;
    }
    await new Promise((r) => setTimeout(r, 300 * 2 ** i));
  }
}

重试间隔按指数退避,尽量别一下子连续打,服务器本来就忙的时候更容易被打垮。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。