axios 实现请求重试

前景提要:
ts 简易封装 axios,统一 API
实现在 config 中配置开关拦截器

请求重试的核心是可以重放请求,具体实现就是在 axios 中,拿到当前请求的 config 对象,再用 axios 实例,就能重放请求。

在无感刷新 token 中,当 access token 过期,使用 refresh token 刷新后,就需要再次对业务接口重放请求。

上面是一种请求重试的场景,一般情况下也不需要重试,所以我们这里讲的请求重试,指的都是请求网络错误的情况下需要重试。

比如断网了,然后重试。而不是因为接口返回 code 如 401 就重试。因为接口返回 401,从网络层面上讲,这是没有失败的,http 状态码是 200,返回 401 只是业务失败。

比起断网,更常见的网络错误下需要重试的是请求超时。

通过错误拦截器实现请求重试。整个请求过程是一个递归。

第一次请求失败,触发全局错误拦截,然后一路抛出错误,触发到重试的错误拦截器。判断还有重试次数后,拿到同一个实例重放请求。注意此时第一次请求并未结束,this.instance.request 方法依旧在等待结果。

如果请求依旧失败,则触发第二次请求的全局错误拦截,最后再次触发重试。如果第二次请求重试成功了,此时就拿到了请求结果。并且为了让结果最终被第一次请求捕获,需要在错误拦截器中抛出 fulfilled 状态的 promise 携带结果。

当请求次数用完,则错误拦截器继续抛出错误对象,触发第一次请求的 request 方法的 catch 代码块。宣告整个请求失败。

注意:

  • 一定要以同一个 axios 实例重新发起请求,因为本质是递归,换个一个实例就拿不到重试成功后的请求结果了。
  • 并且还需要在这个重试的错误拦截器中返回一个 fulfilled 状态的 promise,让第一次请求的实例方法捕获。

return Promise.resolve(res); 或 Promise.rejected(234); 都表示返回一个确定了状态的 promise,然后这个 promise 中携带了数据(就是参数)。

typescript 复制代码
import httpRequest from "..";
import { MyAxiosError, MyAxiosRequestConfig } from "./request";

const MAX_RETRY_COUNT = 3;
const DELAY_TIME = 2000;

let currentCount = 1;
/**
 * 请求重试
 * @param err 错误对象
 * @returns 重试机会用完抛出错误,重试成功则返回请求结果
 */
export async function retryRequest(err: MyAxiosError) {
    if (err.config.retry === false) throw err;
    if (err.message === "canceled") throw err; // 过滤手动取消请求的情况

    const config = err.config as MyAxiosRequestConfig;

    if (MAX_RETRY_COUNT >= currentCount && config) {
        console.log(`重试${currentCount}次...`);
        currentCount++;
        await sleep(DELAY_TIME);
        const res = await httpRequest.getInstance().request({ ...config });
        return Promise.resolve(res);
    }
    console.log("重试次数已用完...");
    currentCount = 0;
    throw err;
}

/**
 * 延迟后续代码执行的工具函数,以同步代码阻塞的方式实现延迟:await sleep()
 * @param delayTime 延迟时间
 * @returns Promise
 */
export function sleep(delayTime: number = 1000) {
    return new Promise(resolve => setTimeout(resolve, delayTime));
}
相关推荐
程序猿阿森几秒前
深入解析 NLI:RAG 与大模型防幻觉的“最后一道防线”
前端·人工智能·算法
iCxhust1 小时前
模型:500kW飞轮 10kV输电线路 油田抽油机 同时考虑无功补偿 统计:全年节电量 结果56万度电
前端·css·css3·电力·飞轮
志尊宝2 小时前
AI原生前端开发(011):Chrome 148+内置Gemini Nano入门
前端·chrome·ai-native
Liu.7742 小时前
uniapp swiper 常见问题及修复
前端·uni-app
u0111026752 小时前
图片生成任务的日志记录与敏感信息取舍
前端·图像处理·算法·ai作画
Eastmount2 小时前
[论文阅读] (54)NDSS26 JSIMPLIFIER:动静态与LLM如何协同完成JavaScript解混淆?
javascript·论文阅读·恶意代码分析·智能体安全·ndss
梦想很大很大3 小时前
重新思考 Workrun:AI 时代,我们还需要手动编排 Workflow 吗?
前端·人工智能·后端
Ai-_Man3 小时前
ChatGPT还是不可以导出左侧所有对话,只能点进去单条内容导出,方法不对吗?
开发语言·javascript·人工智能·chatgpt·小程序·ecmascript
小羊没烦恼!3 小时前
深入浅出SQL Server中的死锁
java·开发语言·前端·数据库·后端·spring·c#