mirror of
https://github.com/XiaoDaiGua-Ray/ray-template.git
synced 2025-04-06 03:57:49 +08:00
axios取消器重写
This commit is contained in:
parent
e105726dde
commit
ce83a9c30b
83
src/axios/canceler.ts
Normal file
83
src/axios/canceler.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ray <https://github.com/XiaoDaiGua-Ray>
|
||||||
|
*
|
||||||
|
* @date 2023-02-27
|
||||||
|
*
|
||||||
|
* @workspace ray-template
|
||||||
|
*
|
||||||
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 自动取消重复请求
|
||||||
|
*
|
||||||
|
* 可以根据自己项目进行定制化配置
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { AxiosRequestConfig } from 'axios'
|
||||||
|
|
||||||
|
export default class RequestCanceler {
|
||||||
|
pendingRequest: Map<string, AbortController>
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.pendingRequest = new Map<string, AbortController>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param config 请求体 config
|
||||||
|
* @returns 返回当前请求拼接 key
|
||||||
|
*
|
||||||
|
* @remark 将当前请求 config 生成 request key
|
||||||
|
*/
|
||||||
|
generateRequestKey(config: AxiosRequestConfig): string {
|
||||||
|
const { method, url } = config
|
||||||
|
|
||||||
|
return [
|
||||||
|
url || '',
|
||||||
|
method || '',
|
||||||
|
JSON.stringify(config.params),
|
||||||
|
JSON.stringify(config.data),
|
||||||
|
].join('&')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param config axios request config
|
||||||
|
*
|
||||||
|
* @remark 给请求体添加 signal 属性, 用于取消请求
|
||||||
|
*/
|
||||||
|
addPendingRequest(config: AxiosRequestConfig) {
|
||||||
|
const requestKey: string = this.generateRequestKey(config)
|
||||||
|
|
||||||
|
if (!this.pendingRequest.has(requestKey)) {
|
||||||
|
const controller = new AbortController()
|
||||||
|
|
||||||
|
config.signal = controller.signal
|
||||||
|
this.pendingRequest.set(requestKey, controller)
|
||||||
|
} else {
|
||||||
|
// 如果已经有该 key 则重新挂载 signal
|
||||||
|
config.signal = (
|
||||||
|
this.pendingRequest.get(requestKey) as AbortController
|
||||||
|
).signal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param config axios request config
|
||||||
|
*
|
||||||
|
* @remark 取消该请求, 并且清除 map 中对应 generateRequestKey value
|
||||||
|
*/
|
||||||
|
removePendingRequest(config: AxiosRequestConfig) {
|
||||||
|
const requestKey = this.generateRequestKey(config)
|
||||||
|
|
||||||
|
if (this.pendingRequest.has(requestKey)) {
|
||||||
|
;(this.pendingRequest.get(requestKey) as AbortController).abort()
|
||||||
|
|
||||||
|
this.pendingRequest.delete(requestKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,28 +1,30 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ray <https://github.com/XiaoDaiGua-Ray>
|
||||||
|
*
|
||||||
|
* @date 2023-02-27
|
||||||
|
*
|
||||||
|
* @workspace ray-template
|
||||||
|
*
|
||||||
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 为什么要写这个文件在这儿多此一举呢:
|
||||||
|
* - 考虑到可能需要什么特殊操作, 所以提前写在这儿了
|
||||||
|
* - 可以个性化配置一些东西, 所有配置都会合并到 axios instance config 中
|
||||||
|
* - 当然, 你也可以直接使用 instance
|
||||||
|
*/
|
||||||
|
|
||||||
import request from './instance'
|
import request from './instance'
|
||||||
|
|
||||||
import type { AxiosRequestConfig } from 'axios'
|
import type { AxiosRequestConfig } from 'axios'
|
||||||
|
|
||||||
let controller: AbortController
|
|
||||||
|
|
||||||
const useRequest = (config: AxiosRequestConfig) => {
|
const useRequest = (config: AxiosRequestConfig) => {
|
||||||
controller && controller.abort() // 调用控制器, 取消请求
|
const cfg = Object.assign({}, config, {})
|
||||||
|
|
||||||
controller = new AbortController() // 实例化控制器对象(可以中止一个或多个 `Web` 请求)
|
|
||||||
|
|
||||||
const cfg = Object.assign({}, config, {
|
|
||||||
signal: controller.signal, // 取消请求信号
|
|
||||||
})
|
|
||||||
|
|
||||||
return request(cfg)
|
return request(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useRequest
|
export default useRequest
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* 使用 `axios` 实例
|
|
||||||
*
|
|
||||||
* 可以自动取消重复请求部分
|
|
||||||
*
|
|
||||||
* 使用该方法进行二次的请求封装, 然后可以使用 `import { xxx } from '@use-api/xxx' 导入
|
|
||||||
*/
|
|
||||||
|
@ -1,9 +1,23 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ray <https://github.com/XiaoDaiGua-Ray>
|
||||||
|
*
|
||||||
|
* @date 2022-11-18
|
||||||
|
*
|
||||||
|
* @workspace ray-template
|
||||||
|
*
|
||||||
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
|
*/
|
||||||
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { useDetermineEnv } from '@use-utils/hook'
|
import { useDetermineEnv } from '@use-utils/hook'
|
||||||
|
import RequestCanceler from './canceler'
|
||||||
|
|
||||||
import type { RawAxiosRequestHeaders, AxiosRequestConfig } from 'axios'
|
import type { RawAxiosRequestHeaders, AxiosRequestConfig } from 'axios'
|
||||||
import type { RequestHeaderOptions } from './type'
|
import type { RequestHeaderOptions } from './type'
|
||||||
|
|
||||||
|
const canceler = new RequestCanceler()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param instance axios instance
|
* @param instance axios instance
|
||||||
@ -26,6 +40,9 @@ const server = axios.create({
|
|||||||
baseURL: '', // `import.meta.env`,
|
baseURL: '', // `import.meta.env`,
|
||||||
withCredentials: false, // 是否允许跨域携带 `cookie`
|
withCredentials: false, // 是否允许跨域携带 `cookie`
|
||||||
timeout: 5 * 1000,
|
timeout: 5 * 1000,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
server.interceptors.request.use(
|
server.interceptors.request.use(
|
||||||
@ -47,6 +64,9 @@ server.interceptors.request.use(
|
|||||||
},
|
},
|
||||||
]) // 自定义请求头
|
]) // 自定义请求头
|
||||||
|
|
||||||
|
canceler.removePendingRequest(request) // 检查是否存在重复请求, 若存在则取消已发的请求
|
||||||
|
canceler.addPendingRequest(request) // 把当前的请求信息添加到 pendingRequest 表中
|
||||||
|
|
||||||
return request
|
return request
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
@ -56,11 +76,15 @@ server.interceptors.request.use(
|
|||||||
|
|
||||||
server.interceptors.response.use(
|
server.interceptors.response.use(
|
||||||
(response) => {
|
(response) => {
|
||||||
|
canceler.removePendingRequest(response.config)
|
||||||
|
|
||||||
const { data } = response
|
const { data } = response
|
||||||
|
|
||||||
return Promise.resolve(data)
|
return Promise.resolve(data)
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
canceler.removePendingRequest(error.config || {})
|
||||||
|
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -63,7 +63,6 @@ const Axios = defineComponent({
|
|||||||
<NLayoutHeader bordered>
|
<NLayoutHeader bordered>
|
||||||
<NCard title="请求函数">
|
<NCard title="请求函数">
|
||||||
基于 axios 封装, 能够自动取消连续请求, 避免重复渲染造成问题.
|
基于 axios 封装, 能够自动取消连续请求, 避免重复渲染造成问题.
|
||||||
可在该示例中测试, 并且打开控制台的网络选项卡查看
|
|
||||||
</NCard>
|
</NCard>
|
||||||
</NLayoutHeader>
|
</NLayoutHeader>
|
||||||
<NLayoutHeader bordered>
|
<NLayoutHeader bordered>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user