cancelToken
cancelToken简介
cancelToken是axios用来取请求的api
针对菜单的路由页面跳转,我们可以取消请求跳转前的请求,以提升页面性能减少不必要的等待。
AbortController简介
在axios中,新增AbortController,将CancelToken标记为**deprecated**
MDN中介绍AbortController
AbortController接口表示一个控制器对象,允许你根据需要中止一个或多个 Web 请求。你可以使用
[AbortController.AbortController()](https://developer.mozilla.org/zh-CN/docs/Web/API/AbortController/AbortController)构造函数创建一个新的AbortController。使用[AbortSignal](https://developer.mozilla.org/zh-CN/docs/Web/API/AbortSignal)对象可以完成与 DOM 请求的通信。
实现axios的CancelToken
api.js
import axios from "axios";
const CancelToken = axios.CancelToken;
const sourceList = []
const opt = {
//拓展默认属性
//baseURL、cache、contentType、timeout等
timeout: 80000, //统一设置超时时间
}
let instance = axios.create(opt);
function handleCancelToken(CancelToken, sourceList) {
if(!CancelToken){
return
}
return {
source: function source() {
const source = CancelToken.source();
sourceList.push(source)
return {
token: source?.token,
cancel: function cancel(message){
if(source?.canceled){
return;
}
const index = sourceList?.findIndex(function (s) {
return s === source
})
index !== -1 && source?.splice(index, 1)
source?.cancel(message)
}
}
}
}
}
instance.interceptors.request.use(config => {
//模拟封装配置项目
//针对每一个请求添加一个CancelToken,在handleCancelToken内部记录请求的source
const defaultParams = Object.assign(config, {
cancelToken: handleCancelToken(CancelToken, sourceList)?.source()?.token
})
console.log(defaultParams, 'config')
return defaultParams
}, err => {
console.log(err, '请求错误')
})
instance.interceptors.response.use(res => {
console.log(res, '响应结果')
return res
}, err => {
//TODO:错误码处理、Canceloken错误处理
console.log(err, '响应错误')
if(err?.message === '"myCanceledError"'){
return
}
})
//手动取消请求 -> 路由切换后取消请求
instance.abortAll = function(message){
//**注意:第一个请求没有被取消**
sourceList?.forEach( source => {
source.canceled = true
source.cancel(message)
})
sourceList.length = 0
}
export default instance;
测试文件:test.tsx
import api from './api'
export default function Index() {
const send = () => {
//let controller = new AbortController();
//const signal = controller.signal;
api({
url: 'https://mdn.github.io/dom-examples/abort-api/sintel.mp4',
method: 'get',
params: {
//signal: signal
}
})
}
const cancel= () => {
//取消请求
api?.abortAll('myCanceledError')
}
return (
<div>
<button onClick={send}>
点击请求
</button>
<button onClick={cancel}>
取消请求
</button>
</div>
)
}
Prompt → ‘react-router-dom’
const promptCallback = () => {
//todo
api?.abortAll('myCanceledError')
}
<Prompt when={true} message={promptCallback} />
AbortController同理
controller = new AbortController();