关于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 这种更为优雅的写法,核心的请求取消实现逻辑,还是在于前面的两种,拦截器也只是实现的位置不同罢了,所以这里就不做赘述。

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

相关推荐
小江的记录本14 小时前
【JVM虚拟机】垃圾回收GC:垃圾回收算法:标记-清除、标记-复制、标记-整理、分代收集(附《思维导图》+《面试高频考点清单》)
java·jvm·后端·python·算法·安全·面试
XinZong14 小时前
实测OpenClaw虾淘:全民工具AI时代,冷门非工具类的Skill还能出圈吗?
javascript
kjs--14 小时前
浏览器书签执行脚本
前端
烛衔溟14 小时前
TypeScript 类的类型 —— 作为类型使用
javascript·ubuntu·typescript
之歆14 小时前
Day16_JavaScript 轮播图与事件工程实战(下篇)
服务器·开发语言·前端·javascript·网络·性能优化
沄媪15 小时前
CSRF 跨站请求伪造
前端·ctf·csrf
小江的记录本15 小时前
【JVM虚拟机】垃圾回收GC:垃圾收集器:G1:Region分区、Mixed GC、回收流程、适用场景(高频)(附《思维导图》+《面试高频考点清单》)
java·jvm·后端·python·spring·spring cloud·面试
kyriewen15 小时前
我关掉了Copilot:因为我写的代码出现在了别人的建议里
前端·javascript·ai编程
欧雷殿16 小时前
从「吸引子引导工程」看我的「一人公司」实践
前端·人工智能·后端