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