关于axios终止请求的思考

背景

Hello,everyone~

笔者前段时间面字节二面,面试官提出了一个问题是说,如果发出的请求在 10s 之内没有响应,我们应该怎么去取消这个请求。

我当时最先说了取消请求的 API 是 cancelToken 还有 AbortController,然后提出了两个思路,一个是新增标志位,在 cancelToken 里面设置时间,另一个是在 axios response 拦截器里面做处理。

然后面试官一直说这不够优雅,最后我还是没有答出来,最后告诉我可以用 Promise.race 来实现,接下来让我一个一个方案的来说:

方案一

使用cancelToken参数,axios自带cancelToken参数

学习链接

js 复制代码
this.axios({
     method: "post",
     url,
     data,
     cancelToken: new CancelToken(function executor(c) {
         cancel = c;
     }),
 })
 .then((response) => {
     clearTimeout(timer);
     if (!response.data.hasError) {
         this.$message.success("数据获取成功!");
         const results = response.data.result;
     } else {
         this.$message.error("数据获取失败!");
     }
 })
 .catch((error) => {
     clearTimeout(timer);
     if (error.response) {
         this.$message.error("数据获取失败!");
     }
 });

这里需要着重说一下 timer 和 cancel 的写法:

js 复制代码
const CancelToken = axios.CancelToken;
let cancel;
let timer = setTimeout(() => {
    cancel();
    this.$message.error("连接超时,请检查网络!")
}, 10000);

这里的核心逻辑就是存在一个包含 cancel 的 timer,无论是我收到了 result 还是发生了报错,我都会取消这个请求,但是如果说上面的两种行为都没有命中,那这个请求就会被 cancel 掉。

值得一提的是 setTimeout 肯定是存在误差的,这点我们没法去否认,就算我们使用第三种优雅的方式,我们依然会使用 setTimeout。

方案二

这个方式就是面试官强推的优雅的方式,我当时听到这个方式的时候还在疑惑可行性,后面重温了一下 Promise.race 之后,发现,这个真的太优雅了,具体的写法可以看看下面:

js 复制代码
function delayPromise(ms) {
    return new Promise(function (resolve) {
        setTimeout(resolve, ms);
    });
}
function timeoutPromise(promise, ms) {
    var timeout = delayPromise(ms).then(function () {
            throw new Error('Operation timed out after ' + ms + ' ms');
        });
    return Promise.race([promise, timeout]);
}

这里如果说我的 delay 时间是 10s,那我ms就设置为 10000,然后在两者之间发生竞速,如果说 promise 先执行了,那我就啥都不说,如果说 promise 是后执行的,那它就根本不会被执行了,用 Promise.race 取代了前面聊的笨笨的 API。优雅,太优雅了。

额外思考

写文章的时候,最开始是分成了三个方法,两个是前面写到的 cacelToken 和 Promice.race,其实还想到了一个最开始提到的axios拦截器,后来仔细的看了一下,我理解拦截器本身只是一个形式,我做请求的取消,既可以使用 cacelToken 这种 API,也可以使用 Promise.race 这种更为优雅的写法,核心的请求取消实现逻辑,还是在于前面的两种,拦截器也只是实现的位置不同罢了,所以这里就不做赘述。

那么这就是本篇文章的全部内容啦~

相关推荐
Pedantic27 分钟前
SwiftUI 手势层级(Gesture Hierarchy)详解
前端
飘尘43 分钟前
前端转型全栈(Java后端)的快速上手指引
前端·后端·全栈
一颗烂土豆1 小时前
Meshopt 压缩深度解析,为什么它比 Draco 更快
前端·javascript·webgl
浏览器工程师2 小时前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
雨季mo浅忆2 小时前
VSCode自动格式化三要素
前端
爱勇宝3 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
kyriewen3 小时前
同事每天催我 Code Review,我写了个脚本让 AI 替我 review PR——现在他反过来催 AI 了
前端·javascript·ai编程
user20585561518136 小时前
Windows 项目安装时报 `node-sass` 错误,如何快速处理
前端
LiaCode6 小时前
Redis 在生产项目的使用
前端·后端