怎样优雅地为 Axios 设置失败重试与最大实验次数

打印 上一主题 下一主题

主题 1575|帖子 1575|积分 4725

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
        在 Vue 3 中,除了使用自界说的 useRequest 钩子函数外,还可以通过 axios 的拦截器 axios-retry 插件实现接口哀求失败后的重试逻辑。以下是两种详细方案的实现方式:
方案一:使用 axios 拦截器实现重试

       实现步骤: 通过 axios 的响应拦截器捕获错误,并在拦截器内部实现重试逻辑。

        1、设置 axios 实例:在 Vue 项目的入口文件(如 main.js)中设置 axios。
        2、添加响应拦截器:在拦截器中捕获错误,并根据条件进行重试。
        3、递归重试:在拦截器中控制重试次数和延长。
  1. // main.js 或单独的 axios 配置文件
  2. import axios from 'axios';
  3. // 配置 axios 实例
  4. const axiosInstance = axios.create({
  5.     baseURL: '/api', // 根路径
  6.     timeout: 10000, // 超时时间
  7. });
  8. // 响应拦截器:处理错误并重试
  9. axiosInstance.interceptors.response.use((response) => response, // 成功响应直接返回
  10.     async (error) => {
  11.                 const config = error.config;
  12.                 const status = error.response?.status;
  13.                 const maxRetries = 5; // 最大重试次数
  14.                 const retryDelay = 1000; // 重试间隔(毫秒)
  15.                 // 如果没有重试次数或达到最大次数,直接抛出错误
  16.                 if (!config || !config._retryCount) {
  17.                         config._retryCount = 0;
  18.                 }
  19.                
  20.                 if (config._retryCount >= maxRetries) {
  21.                         return Promise.reject(error);
  22.                 }
  23.                 // 增加重试次数
  24.                 config._retryCount += 1;
  25.                 // 只对特定状态码(如 408、5xx)重试
  26.                 if (
  27.                         [408, 500, 502, 503, 504].includes(status) ||
  28.                         (status === 401 && config.url.includes('/refresh-token')) // 示例:401 时重试刷新 token
  29.                 ) {
  30.                         // 等待一段时间后重试
  31.                         await new Promise((resolve) => setTimeout(resolve, retryDelay * config._retryCount));
  32.                         // 重新发送请求
  33.                         return axiosInstance(config);
  34.                 }
  35.                 // 其他错误直接抛出
  36.                 return Promise.reject(error);
  37.     }
  38. );
  39. // 导出配置好的 axios 实例
  40. export default axiosInstance;
复制代码
使用示例(在 Vue 组件中)

  1. <template>
  2.         <div>
  3.                 <button @click="fetchData">获取数据</button>
  4.                 <div v-if="loading">加载中...</div>
  5.                 <div v-else-if="data">数据:{{ data }}</div>
  6.                 <div v-else-if="error">错误:{{ error.message }}</div>
  7.         </div>
  8. </template>
  9. <script setup>
  10. import axiosInstance from '@/utils/axios'; // 导入配置好的 axios 实例
  11. import { ref } from 'vue';
  12. const loading = ref(false);
  13. const data = ref(null);
  14. const error = ref(null);
  15. const fetchData = async () => {
  16.         try {
  17.                 loading.value = true;
  18.                 const response = await axiosInstance.get('/data');
  19.                 data.value = response.data;
  20.                 error.value = null;
  21.         } catch (err) {
  22.                 error.value = err;
  23.         } finally {
  24.                 loading.value = false;
  25.         }
  26. };
  27. </script>
复制代码
        1、拦截器全局生效:全部通过 axiosInstance 发起的哀求都会经过拦截器,自动处理重试逻辑。可通过设置 config 参数(如 config._retryCount)控制重试次数。
        2、重试条件:根据 HTTP 状态码(如 408、5xx)决定是否重试。可扩展为根据业务逻辑(如 token 过期后刷新)触发重试。
        3、递归重试:通过 axiosInstance(config) 重新发送哀求,递归调用拦截器。必要手动维护 config._retryCount 来计数。

方案二:使用 axios-retry 插件

        通过 axios-retry 插件快速实现重试逻辑,无需手动编写递归逻辑。
        1、安装插件
  1. npm install axios-retry
复制代码
        2、设置 axios 实例
  1. // main.js 或单独的 axios 配置文件
  2. import axios from 'axios';
  3. import axiosRetry from 'axios-retry';
  4. const axiosInstance = axios.create({
  5.         baseURL: '/api',
  6.         timeout: 10000,
  7. });
  8. // 配置重试策略
  9. axiosRetry(axiosInstance, {
  10.         retries: 5, // 最大重试次数
  11.         retryDelay: (retryCount) => {
  12.                 return retryCount * 1000; // 指数退避:1s、2s、3s...
  13.         },
  14.         retryCondition: (error) => {
  15.                 // 自定义重试条件(如针对特定状态码)
  16.                 if (error.response) {
  17.                         return [408, 500, 502, 503, 504].includes(error.response.status);
  18.                 }
  19.                 return axiosRetry.isNetworkError(error); // 网络错误自动重试
  20.         },
  21. });
  22. export default axiosInstance;
复制代码
        3、使用示例(与方案一相同)
  1. <template>
  2.   <!-- 同上 -->
  3. </template>
  4. <script setup>
  5. import axiosInstance from '@/utils/axios'; // 已配置重试的 axios 实例
  6. // 同上
  7. </script>
复制代码

关键点说明

        1、插件优势:开箱即用,代码简便。支持自界说重试条件、延长策略(如指数退避)。
内置对网络错误(如超时)的自动重试。
        2、机动性:可通过 retryCondition 函数机动控制重试条件。支持 retryDelay 函数实现动态延长(如指数退避)。

对比与选择

方案优点缺点拦截器手动实现完全自界说逻辑,无依靠代码冗余,需手动维护计数器axios-retry 插件简朴易用,开箱即用需引入第三方依靠
留意事项

        1、避免无限循环:必须设置最大重试次数(如 maxRetries 或 retries 参数)。确保重试条件不会无限触发(如 401 未授权 需结合 token 刷新逻辑)。
        2、错误范例区分:对于 4xx 客户端错误(如 400、401、403),通常不建议重试,需业务逻辑处理(如跳转登录页)。对 5xx 服务端错误(如 500、503)或网络错误(如超时),可安全重试。
        3、性能优化:使用 指数退避(如 retryDelay: (count) => Math.pow(2, count) * 1000)减少并发重试的压力。结合 限流(如 maxRetries 与 retryDelay 组合)避免频仍哀求。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张春

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表