UniApp的request请求自动重试机制实现

UniApp的request请求自动重试机制实现

你好,UniApp世界的探险家们! 🌍

大家好!今天我们要一起探讨一个非常有趣且实用的话题:如何在UniApp中实现request请求的自动重试机制。想象一下,你正在开发一个APP,用户在点击某个按钮时需要发送一个网络请求。但有时候,网络可能会“打个盹儿” 😴,导致请求失败。这时候,如果能自动再试一次,用户体验是不是会好很多呢?😏

那么,我们今天就来聊聊如何优雅地实现这个功能。准备好了吗?让我们开始吧!


什么是自动重试机制?

简单来说,自动重试机制就是在网络请求失败时,程序会自动再次发起请求,而不是直接告诉用户“出错了”。这样可以避免用户频繁手动刷新页面或重新操作,提升用户体验。

为什么要实现自动重试?

  1. 网络波动:移动网络不稳定是常见的问题,尤其是在切换Wi-Fi和4G/5G时,可能会导致请求失败。
  2. 服务器负载:当服务器负载过高时,可能会返回503(服务不可用)等错误,此时重试可以帮助用户顺利完成操作。
  3. 用户友好:自动重试可以让用户无感知地完成操作,减少他们的焦虑感。

UniApp中的request方法

在UniApp中,uni.request是用于发起HTTP请求的核心API。它的基本用法如下:

uni.request({
  url: 'https://example.com/api/data',
  method: 'GET',
  success(res) {
    console.log('请求成功:', res.data);
  },
  fail(err) {
    console.error('请求失败:', err);
  }
});

但是,当我们遇到网络问题时,fail回调会被触发,这时候我们需要做些什么呢?🤔


实现自动重试的思路

要实现自动重试,我们需要考虑以下几个问题:

  1. 重试几次:不能无限次重试,否则可能会陷入死循环。通常我们会设置一个最大重试次数。
  2. 重试间隔:每次重试之间应该有一定的间隔时间,避免短时间内频繁请求服务器。
  3. 重试条件:并不是所有错误都需要重试,比如404(资源未找到)这种错误就没有必要重试。
  4. 用户提示:如果重试多次仍然失败,应该给用户一个友好的提示。

代码实现

我们可以封装一个自定义的request函数,加入自动重试的逻辑。下面是一个简单的实现:

function requestWithRetry(options, retryCount = 3, delay = 1000) {
  return new Promise((resolve, reject) => {
    function makeRequest(attempt = 1) {
      uni.request({
        ...options,
        success(res) {
          resolve(res); // 请求成功,直接返回结果
        },
        fail(err) {
          if (attempt >= retryCount) {
            // 达到最大重试次数,放弃重试
            reject(err);
            return;
          }

          console.warn(`第 ${attempt} 次请求失败,将在 ${delay}ms 后重试...`);

          // 等待一段时间后重试
          setTimeout(() => {
            makeRequest(attempt + 1);
          }, delay);
        }
      });
    }

    makeRequest(); // 第一次请求
  });
}

参数说明

  • optionsuni.request的配置项,包括urlmethoddata等。
  • retryCount:最大重试次数,默认为3次。
  • delay:每次重试之间的间隔时间,默认为1秒(1000ms)。

使用示例

requestWithRetry({
  url: 'https://example.com/api/data',
  method: 'GET'
}).then(res => {
  console.log('最终请求成功:', res.data);
}).catch(err => {
  console.error('请求失败,已达到最大重试次数:', err);
});

进阶优化:根据错误码决定是否重试

并不是所有的错误都需要重试。例如,404错误表示资源不存在,重试也不会有帮助。因此,我们可以根据HTTP状态码来决定是否进行重试。

function requestWithRetry(options, retryCount = 3, delay = 1000) {
  return new Promise((resolve, reject) => {
    function makeRequest(attempt = 1) {
      uni.request({
        ...options,
        success(res) {
          // 如果状态码是2xx,表示请求成功
          if (res.statusCode >= 200 && res.statusCode < 300) {
            resolve(res);
          } else {
            // 处理非2xx的状态码
            handleNonSuccessStatusCode(res, attempt);
          }
        },
        fail(err) {
          if (attempt >= retryCount) {
            reject(err);
            return;
          }

          console.warn(`第 ${attempt} 次请求失败,将在 ${delay}ms 后重试...`);
          setTimeout(() => {
            makeRequest(attempt + 1);
          }, delay);
        }
      });
    }

    function handleNonSuccessStatusCode(res, attempt) {
      const statusCode = res.statusCode;

      // 只对某些特定的状态码进行重试
      if ([500, 502, 503, 504].includes(statusCode)) {
        if (attempt < retryCount) {
          console.warn(`状态码 ${statusCode},将在 ${delay}ms 后重试...`);
          setTimeout(() => {
            makeRequest(attempt + 1);
          }, delay);
        } else {
          reject(res);
        }
      } else {
        // 对于其他状态码,直接拒绝
        reject(res);
      }
    }

    makeRequest(); // 第一次请求
  });
}

错误码表

HTTP状态码 描述 是否重试
200-299 成功
400 请求无效
401 未授权
403 禁止访问
404 资源未找到
500 内部服务器错误
502 网关错误
503 服务不可用
504 网关超时

结合async/await简化代码

如果你喜欢使用async/await来编写异步代码,那么我们可以进一步简化代码结构。以下是结合async/await的版本:

async function requestWithRetry(options, retryCount = 3, delay = 1000) {
  for (let attempt = 1; attempt <= retryCount; attempt++) {
    try {
      const res = await new Promise((resolve, reject) => {
        uni.request({
          ...options,
          success(res) {
            resolve(res);
          },
          fail(err) {
            reject(err);
          }
        });
      });

      // 检查状态码
      if (res.statusCode >= 200 && res.statusCode < 300) {
        return res;
      } else {
        handleNonSuccessStatusCode(res, attempt);
      }
    } catch (err) {
      if (attempt === retryCount) {
        throw err; // 达到最大重试次数,抛出错误
      }

      console.warn(`第 ${attempt} 次请求失败,将在 ${delay}ms 后重试...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

// 使用示例
try {
  const res = await requestWithRetry({
    url: 'https://example.com/api/data',
    method: 'GET'
  });
  console.log('最终请求成功:', res.data);
} catch (err) {
  console.error('请求失败,已达到最大重试次数:', err);
}

总结

通过今天的分享,我们学会了如何在UniApp中实现request请求的自动重试机制。我们不仅实现了基本的重试功能,还根据HTTP状态码进行了优化,确保只对可重试的错误进行重试。最后,我们还使用了async/await来简化代码结构,让代码更加简洁易读。

希望这篇文章对你有所帮助!如果你有任何问题或建议,欢迎在评论区留言。😊

下次见!🌟


参考资料


祝你编码愉快!🚀

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注