Vue 取消 axios 重复请求,将性能优化进行到底(你知道发出去的请求还能这么取消吗?)

53 阅读5分钟

总结

我在成长过程中也是一路摸爬滚打,没有任何人的指点,所以走的很艰难。例如在大三的时候,如果有个学长可以阶段性的指点一二,如果有已经工作的师兄可以告诉我工作上需要什么,我应该前面的三年可以缩短一半;后来去面试bat,失败了有5、6次,每次也不知道具体是什么原因,都是靠面试回忆去猜测可能是哪方面的问题,回来学习和完善,当你真正去招人的时候,你就会知道面试记录是多么重要,面试官可以从面试记录里看到你的成长,总是去面试,总是没有成长,就会被定义为缺乏潜力。

image image 开源分享:docs.qq.com/doc/DSmRnRG…

let xhr = new XMLHttpRequest();

xhr.open("GET", "https://user/12345", true);

xhr.send();

setTimeout(() => xhr.abort(), 1000);

对于 axios 来说,我们可以通过 axios 内部提供的 CancelToken 来取消请求,其有两种方式,我们一一举例。

1、CancelToken.source 工厂

我们可以使用 CancelToken.source 工厂方法创建 cancel token

let CancelToken = axios.CancelToken;

let source = CancelToken.source();

// get请求

axios.get('/user/12345', {

cancelToken: source.token

}).catch(function(thrown) {

if (axios.isCancel(thrown)) {

console.log('Request canceled', thrown.message);

} else {

// 处理错误

}

});

// post请求

axios.post('/user/12345', {

name: 'leo'

}, {

cancelToken: source.token

})

// 取消请求(传入的参数是可选的)

source.cancel('Operation canceled by the user.');

实例

如下,当我们点击搜索按钮,发送一个请求

现在,我们设置低网速来模拟请求较慢(处于pending)的情况

此时,当我们连续多次点击按钮,将出现如下情形

在上一个请求还未响应完成时,我们又发送了重复的请求。其实在上一次请求响应之前,下一次重复请求都是不必要,会造成资源损耗、性能下降,甚至涉及到对数据修改操作时,多个重复请求可能产生意外的bug。

此时,取消重复请求就变得尤为重要。

那么,对于这个例子,我们如何使用 CancelToken.source 工厂方法,以达到取消重复请求的目的?

优化版

此时,如果我们连续多次点击按钮,结果如下

在上一次请求未响应完成,发起重复请求,则将上一次请求取消,以达到优化效果。

2、CancelToken 构造函数

我们也可以通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token

let CancelToken = axios.CancelToken;

let cancel;

axios.get('/user/12345', {

cancelToken: new CancelToken(function executor(c) {

// executor 函数接收一个 cancel 函数作为参数

cancel = c;

})

});

// 取消请求

cancel();

实例

如下方式也能达到取消重复请求的效果

我们知道,发出去的请求(处于pending阶段)可以使用以上两种方式进行取消或中断。那么,在真实的项目中,我们可能需要为全部的请求进行此项优化(取消重复请求),那又该如何去实现?

全局请求优化


这里会涉及到一个问题,我们为全局的请求进行此项优化时,如何判断是否为重复的请求呢?如我在发送1请求,紧接着去发送2请求,此时不算是重复请求,不需要取消;而当发送1请求,1请求还未响应完成时紧接着再去发送1请求,此时判定为重复请求,则执行取消上一次重复请求的操作。

1、如何判断重复请求?

当请求方式、请求 URL 和请求参数都一样时,我们就可以认为请求是一样的。因此在每次发起请求时,我们就可以根据当前请求的请求方式、请求 URL 地址和请求参数来生成一个唯一的 key,同时为每个请求创建一个专属的 CancelToken,然后把 key 和 cancel 函数以键值对的形式保存到 Map 对象中,使用 Map 的好处是可以快速的判断是否有重复的请求

let pendingRequest = new Map();

// 生成唯一的key

let requestKey = [method, url, JSON.stringify(params), JSON.stringify(data)].join('&');

let cancelToken = new CancelToken(function executor(cancel) {

if(!pendingRequest.has(requestKey)){

// 如果发送的请求不存在,则进行保存

pendingRequest.set(requestKey, cancel); // 保存cancel函数,以便后续执行取消请求操作

}

})

当出现重复请求的时候,我们就可以使用 cancel 函数来取消前面已经发出的请求,在取消请求之后,我们还需要把取消的请求从 pendingRequest 中移除。

2、如何取消重复请求?

因为我们需要为全局请求进行此优化,此时可以在拦截器上添加相关配置。

在配置请求拦截器和响应拦截器前,我们先定义3个功能辅助函数。

getRequestKey:用于根据当前请求的信息,生成唯一的请求 key:

// 函数返回唯一的请求key

function getRequestKey(config) {

let { method, url, params, data } = config;

return [method, url, JSON.stringify(params), JSON.stringify(data)].join("&");

}

addPendingRequest:用于把当前请求信息添加到pendingRequest对象中:

let pendingRequest = new Map();

function addPendingRequest(config) {

let requestKey = getRequestKey(config);

config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {

if (!pendingRequest.has(requestKey)) {

pendingRequest.set(requestKey, cancel);

}

});

}

removePendingRequest:检查是否存在重复请求,若存在则取消已发的请求:

function removePendingRequest(config) {

let requestKey = getRequestKey(config);

if (pendingRequest.has(requestKey)) {

// 如果是重复的请求,则执行对应的cancel函数

let cancel = pendingRequest.get(requestKey);

cancel(requestKey);

// 将前一次重复的请求移除

pendingRequest.delete(requestKey);

}

}

3、配置拦截器

请求拦截器

axios.interceptors.request.use(

function (config) {

// 检查是否存在重复请求,若存在则取消已发的请求

removePendingRequest(config);

// 把当前请求信息添加到pendingRequest对象中

addPendingRequest(config);

return config;

},

function (error) => {

return Promise.reject(error);

}

);

响应拦截器

axios.interceptors.response.use(

function (response) => {

// 从pendingRequest对象中移除请求

removePendingRequest(response.config);

return response;

},

function (error) => {

js基础

1)对js的理解? 2)请说出以下代码输出的值? 3)把以下代码,改写成依次输出0-9 4)如何区分数组对象,普通对象,函数对象 5)面向对象、面向过程 6)面向对象的三大基本特性 7)XML和JSON的区别? 8)Web Worker 和webSocket? 9)Javascript垃圾回收方法? 10)new操作符具体干了什么呢? 11)js延迟加载的方式有哪些? 12)WEB应用从服务器主动推送Data到客户端有那些方式?

js基础.PNG

前16.PNG

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】