智享教程网
白蓝主题五 · 清爽阅读
首页  > 日常经验

网络请求如何重试?这些实用方法帮你稳住连接

为什么需要重试网络请求

平时写前端或者做小程序开发,经常会遇到接口突然抽风的情况。比如用户点个提交按钮,页面卡一下提示“网络错误”,刷新一下又好了。这种情况大概率不是代码写错了,而是网络抖动导致请求失败。这时候,如果能在代码里自动重试几次,体验就会好很多。

什么情况下该重试

并不是所有失败都要重试。比如返回 400 参数错误,再发十次也没用。但像 502、503 或者直接超时、断网这类问题,多试一两次往往就能成功。特别是移动端用户,网络环境复杂,地铁里、电梯中信号不稳定,适当重试能显著降低报错率。

手动实现一个简单的重试逻辑

最直接的方式是在 fetch 或 axios 这类请求外面包一层重试函数。下面是个用 fetch 配合 Promise 实现的简单例子:

function requestWithRetry(url, options = {}, retries = 3) {
  return fetch(url, options)
    .then(res => {
      if (!res.ok && retries > 0) {
        return requestWithRetry(url, options, retries - 1);
      }
      return res;
    })
    .catch(err => {
      if (retries > 0) {
        return requestWithRetry(url, options, retries - 1);
      }
      throw err;
    });
}

这个函数默认最多重试三次,只要失败就递归调用自己,直到成功或次数用完。虽然简单,但在大多数场景下够用了。

加上延迟,避免频繁冲击服务

如果失败后立刻重试,可能服务器还没恢复就被新请求压垮了。更好的做法是加点延迟,比如每次等几百毫秒再试。可以用 setTimeout 包一层:

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function requestWithBackoff(url, options = {}, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const res = await fetch(url, options);
      if (res.ok) return res;
    } catch (err) {
      if (i === retries - 1) throw err;
      await delay(2 ** i * 500); // 指数退避
    }
  }
}

这里用了指数退避策略,第一次等 500ms,第二次 1s,第三次 2s,避免短时间内重复请求。

使用现成工具库更省心

如果项目里请求重试需求多,可以考虑用 axios-retryky 这类支持重试的库。比如 axios-retry 只需几行代码就能开启:

const axios = require('axios');
const axiosRetry = require('axios-retry');

axiosRetry(axios, { retries: 3 });

axios.get('/api/data').then(res => console.log(res.data));

连错误类型判断都帮你做了,只对网络类错误重试,不影响正常业务逻辑。

别忘了给用户一点反馈

后台自动重试是好事,但如果界面一直卡着不动,用户可能会以为没反应,忍不住狂点。建议在重试期间显示“正在重试”或加载动画,让用户知道系统还在工作。

重试不是万能的

加了重试不代表所有问题都能解决。如果服务器持续崩溃,重试只会增加负担。合理设置最大次数和超时时间,避免无限循环。另外,对于提交订单这类操作,要确保接口幂等,否则可能造成重复下单。