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

Ajax请求自动重连实现:网络不稳定时的实用解决方案

在开发网页应用时,经常会遇到网络波动导致Ajax请求失败的情况。比如用户在地铁里刷页面,突然进入隧道,请求发不出去;或者服务器短暂卡顿,返回502错误。这时候如果能让请求自动重试,体验会好很多。

为什么需要自动重连

想象一下,用户提交了一个订单,点击后页面没反应,刷新一下又发现订单已经生成了。这种情况很可能就是请求发送成功了,但响应没收到,前端没得到反馈。如果请求能自动重连几次,大概率就能拿到结果,避免重复提交。

基本思路:封装Ajax并加入重试机制

我们可以用原生fetch或jQuery的$.ajax,在外层封装一个带重试逻辑的函数。核心就是监听请求失败,然后在一定延迟后重新发起,直到成功或达到最大重试次数。

function ajaxWithRetry(url, options = {}, maxRetries = 3, delay = 1000) {
  return new Promise((resolve, reject) => {
    function attempt(retryCount) {
      fetch(url, options)
        .then(response => {
          if (!response.ok) throw new Error(`HTTP ${response.status}`);
          return response.json();
        })
        .then(resolve)
        .catch(error => {
          if (retryCount >= maxRetries) {
            reject(error);
          } else {
            setTimeout(() => {
              console.log(`请求失败,${delay}ms后重试(第${retryCount}次)`);
              attempt(retryCount + 1);
            }, delay);
          }
        });
    }
    attempt(1);
  });
}

实际使用示例

比如我们要获取用户信息,在弱网环境下希望最多重试两次:

ajaxWithRetry('/api/user/profile', {
  method: 'GET'
}, 2, 1500)
.then(data => {
  console.log('用户数据:', data);
})
.catch(err => {
  console.error('最终失败:', err.message);
});

进阶优化:指数退避

连续重试间隔固定时间可能不太友好。可以改成指数增长,比如第一次等1秒,第二次等2秒,第三次等4秒,减轻服务器压力。

setTimeout(() => {
  attempt(retryCount + 1);
}, delay * Math.pow(2, retryCount - 1));

只对特定错误重试

不是所有失败都值得重试。比如404找不到接口,再试也没用。应该只对网络错误、5xx服务器问题或超时做重连。

.catch(error => {
  const networkError = ['Failed to fetch', 'NetworkError'].some(msg => 
    error.message.includes(msg)
  );
  const serverError = error.message.includes('HTTP 5');

  if (!(networkError || serverError)) {
    return reject(error); // 不重试,直接抛出
  }

  if (retryCount >= maxRetries) {
    reject(error);
  } else {
    // 继续重试...
  }
});

结合业务场景灵活控制

有些操作不能重复提交,比如支付请求。这时候可以在封装时加个标记,确保即使重连也只发一次。而轮询类请求,比如查订单状态,反而可以主动多试几次。

把重连逻辑抽成工具函数后,项目里所有关键请求都可以统一加上这层保护,既不影响原有代码结构,又能显著提升稳定性。