解析NaiveUiAdmin的vue开源项目(二)-CSDN博客
咱们接着学习把
src/utils/http/axios/axiosCancel.ts
import axios, { AxiosRequestConfig, Canceler } from 'axios';
import qs from 'qs';
import { isFunction } from '@/utils/is/index';
// 声明一个 Map 用于存储每个请求的标识 和 取消函数
let pendingMap = new Map<string, Canceler>();
export const getPendingUrl = (config: AxiosRequestConfig) =>
[config.method, config.url, qs.stringify(config.data), qs.stringify(config.params)].join('&');
export class AxiosCanceler {
/**
* 添加请求
* @param {Object} config
*/
addPending(config: AxiosRequestConfig) {
this.removePending(config);
const url = getPendingUrl(config);
config.cancelToken =
config.cancelToken ||
new axios.CancelToken((cancel) => {
if (!pendingMap.has(url)) {
// 如果 pending 中不存在当前请求,则添加进去
pendingMap.set(url, cancel);
}
});
}
/**
* @description: 清空所有pending
*/
removeAllPending() {
pendingMap.forEach((cancel) => {
cancel && isFunction(cancel) && cancel();
});
pendingMap.clear();
}
/**
* 移除请求
* @param {Object} config
*/
removePending(config: AxiosRequestConfig) {
const url = getPendingUrl(config);
if (pendingMap.has(url)) {
// 如果在 pending 中存在当前请求标识,需要取消当前请求,并且移除
const cancel = pendingMap.get(url);
cancel && cancel(url);
pendingMap.delete(url);
}
}
/**
* @description: 重置
*/
reset(): void {
pendingMap = new Map<string, Canceler>();
}
}
以下是对这段代码的分析:
功能概述:
这段代码主要用于管理 Axios 请求的取消操作,以避免重复请求和资源浪费。它通过使用 axios
库进行网络请求,并借助 qs
库来处理查询参数的序列化。同时,引入了一个自定义的工具函数 isFunction
用于判断一个值是否为函数。
主要组成部分:
-
pendingMap
:一个Map
对象,用于存储每个请求的唯一标识和对应的取消函数。pending未决的 -
getPendingUrl
函数:接收一个AxiosRequestConfig
对象作为参数,通过拼接请求方法、URL、请求数据(如果有)和查询参数(如果有)来生成一个唯一的请求标识字符串。 -
AxiosCanceler
类:addPending
方法:在发送请求前调用此方法,它首先尝试移除可能存在的重复请求,然后为当前请求创建一个取消令牌(cancelToken
),并将其与请求的唯一标识一起存储在pendingMap
中。如果pendingMap
中不存在当前请求的标识,则将取消函数添加到pendingMap
中。removeAllPending
方法:用于取消所有挂起的请求。它遍历pendingMap
,调用每个取消函数,并清空pendingMap
。removePending
方法:在请求完成或取消时调用,它根据请求的配置生成唯一标识,检查pendingMap
中是否存在该标识。如果存在,则调用对应的取消函数并从pendingMap
中删除该请求的标识和取消函数。reset
方法:用于重置pendingMap
,将其重新初始化为一个新的Map
对象。
以下是对上述代码逻辑的详细解释
整体目的:
这段代码的主要目的是管理使用 axios
库发送的 HTTP 请求,通过跟踪请求的状态并提供取消特定请求或所有请求的功能,以避免不必要的网络请求和资源浪费。
具体逻辑步骤:
-
导入模块和工具函数:
- 引入
axios
库,以便发送 HTTP 请求。同时,导入了AxiosRequestConfig
和Canceler
类型,分别用于配置请求和表示取消函数。 - 引入
qs
库用于序列化请求参数,以便生成唯一的请求标识。 - 引入自定义的
isFunction
工具函数,用于判断一个值是否为函数。
- 引入
-
定义请求标识存储容器:
- 创建一个
Map
对象pendingMap
,用于存储请求的唯一标识(字符串类型)和对应的取消函数(Canceler
类型)。
- 创建一个
-
生成请求唯一标识函数:
getPendingUrl
函数接收一个AxiosRequestConfig
对象作为参数,通过拼接请求的方法、URL、请求数据(如果有,经过序列化)和查询参数(如果有,经过序列化),生成一个唯一的请求标识字符串。这个唯一标识将用于区分不同的请求,并在pendingMap
中进行存储和管理。
-
定义请求取消管理类
AxiosCanceler
:addPending
方法:- 接收一个
AxiosRequestConfig
对象,表示要添加的请求配置。 - 首先调用
removePending(config)
,可能是为了确保在添加新请求之前,先移除可能存在的重复请求。 - 然后通过
getPendingUrl(config)
生成请求的唯一标识url
。 - 检查请求配置中是否已经存在取消令牌(
cancelToken
)。如果不存在,则创建一个新的取消令牌,并将其与生成的唯一标识关联起来。如果pendingMap
中不存在当前请求的标识,则将取消函数添加到pendingMap
中,以便后续可以通过这个唯一标识来取消该请求。
- 接收一个
removeAllPending
方法:- 遍历
pendingMap
中的每个取消函数。 - 对于每个取消函数,如果它存在并且是一个函数,则调用该取消函数来取消对应的请求。
- 最后清空
pendingMap
,以便重新开始管理新的请求集。
- 遍历
removePending
方法:- 接收一个
AxiosRequestConfig
对象。 - 首先通过
getPendingUrl(config)
生成请求的唯一标识url
。 - 检查
pendingMap
中是否存在该唯一标识。如果存在,则获取对应的取消函数,调用取消函数来取消当前请求,并从pendingMap
中删除该请求的标识和取消函数。
- 接收一个
reset
方法:- 将
pendingMap
重新初始化为一个新的Map
对象,实现对请求管理状态的重置。
- 将
用途:
在复杂的前端应用中,可能会出现多个并发的网络请求,尤其是在用户频繁操作导致重复请求的情况下。这个工具可以帮助管理这些请求,确保不会因为重复请求而浪费资源或导致数据不一致。例如,在用户快速切换页面或进行频繁的搜索操作时,可以使用这个工具来取消之前未完成的请求,提高应用的性能和用户体验。
以下是对这段代码按代码块再次进行更详细的分析:
一、导入模块和工具函数
import axios, { AxiosRequestConfig, Canceler } from 'axios';
import qs from 'qs';
import { isFunction } from '@/utils/is/index';
axios
是一个流行的用于浏览器和 Node.js 的 HTTP 客户端,可以方便地发送各种 HTTP 请求。在这里,导入了axios
库本身以及特定的类型AxiosRequestConfig
(用于配置请求的对象类型)和Canceler
(取消请求的函数类型)。qs
是一个用于处理查询字符串的库,可以将对象序列化为查询字符串格式,方便在发送请求时处理参数。isFunction
是一个自定义的工具函数,用于判断一个值是否为函数,从特定的模块路径中导入。
二、定义请求标识存储容器
// 声明一个 Map 用于存储每个请求的标识 和 取消函数
let pendingMap = new Map<string, Canceler>();
- 创建了一个名为
pendingMap
的Map
数据结构。这个Map
将用于存储每个请求的唯一标识(字符串类型)以及对应的取消函数(Canceler
类型)。这样可以方便地跟踪和管理正在进行的请求,以便在需要时取消它们。
三、生成请求唯一标识函数
export const getPendingUrl = (config: AxiosRequestConfig) =>
[config.method, config.url, qs.stringify(config.data), qs.stringify(config.params)].join('&');
- 定义了一个名为
getPendingUrl
的函数,该函数接收一个AxiosRequestConfig
类型的参数config
。 - 函数内部通过获取请求的方法(
config.method
)、URL(config.url
)、请求数据(如果有,使用qs.stringify(config.data)
将数据序列化为查询字符串格式)以及查询参数(如果有,使用qs.stringify(config.params)
序列化),然后将这些部分用&
连接起来,生成一个唯一的请求标识字符串。 - 这个唯一标识将用于区分不同的请求,以便在
pendingMap
中进行存储和管理。
四、定义请求取消管理类
export class AxiosCanceler {
/**
* 添加请求
* @param {Object} config
*/
addPending(config: AxiosRequestConfig) {
this.removePending(config);
const url = getPendingUrl(config);
config.cancelToken =
config.cancelToken ||
new axios.CancelToken((cancel) => {
if (!pendingMap.has(url)) {
// 如果 pending 中不存在当前请求,则添加进去
pendingMap.set(url, cancel);
}
});
}
- 定义了一个名为
AxiosCanceler
的类,并在其中定义了addPending
方法。 addPending
方法接收一个AxiosRequestConfig
类型的参数config
,表示要添加的请求的配置。- 方法首先调用
this.removePending(config)
,这可能是为了确保在添加新请求之前,先移除可能存在的重复请求。 - 然后调用
getPendingUrl(config)
生成请求的唯一标识url
。 - 接着检查请求配置中是否已经存在取消令牌(
cancelToken
)。如果不存在,则创建一个新的取消令牌,并将其与生成的唯一标识关联起来。如果pendingMap
中不存在当前请求的标识,则将取消函数添加到pendingMap
中,以便后续可以通过这个唯一标识来取消该请求。
/**
* @description: 清空所有pending
*/
removeAllPending() {
pendingMap.forEach((cancel) => {
cancel && isFunction(cancel) && cancel();
});
pendingMap.clear();
}
- 定义了
removeAllPending
方法。 - 这个方法遍历
pendingMap
中的每个取消函数,对于每个取消函数,如果它存在并且是一个函数,则调用该取消函数来取消对应的请求。 - 最后,清空
pendingMap
,以便重新开始管理新的请求集。
/**
* 移除请求
* @param {Object} config
*/
removePending(config: AxiosRequestConfig) {
const url = getPendingUrl(config);
if (pendingMap.has(url)) {
// 如果在 pending 中存在当前请求标识,需要取消当前请求,并且移除
const cancel = pendingMap.get(url);
cancel && cancel(url);
pendingMap.delete(url);
}
}
- 定义了
removePending
方法,接收一个AxiosRequestConfig
类型的参数config
。 - 方法首先通过
getPendingUrl(config)
生成请求的唯一标识url
。 - 然后检查
pendingMap
中是否存在该唯一标识。如果存在,则获取对应的取消函数,调用取消函数来取消当前请求,并从pendingMap
中删除该请求的标识和取消函数。
/**
* @description: 重置
*/
reset(): void {
pendingMap = new Map<string, Canceler>();
}
};
- 定义了
reset
方法。 - 这个方法简单地将
pendingMap
重新初始化为一个新的Map
对象,实现了对请求管理状态的重置。