取消请求
作用于频繁发送请求的场景,上一个请求还没完成,现在需要发送新的请求,那就需要将前面的请求取消掉。
AbortController 接口表示一个控制器对象,允许你根据需要中止一个或多个 Web 请求。
fetch
示例
给 fetch 传递第二个参数,配置 signal
属性,它的值就是 AbortController 实例的 signal
属性。
| let controller;
function fetchVideo() { controller = new AbortController(); const signal = controller.signal; fetch('xxx', { signal }) .then((response) => { console.log('下载完成', response); }) .catch((err) => { console.error(`下载错误:${err.message}`); }); }
|
我们可以创建一个按钮,用来取消请求。调用 AbortController 实例
上的 abort()
方法即可。
1 2 3 4 5 6
| abortBtn.addEventListener('click', () => { if (controller) { controller.abort(); console.log('中止下载'); } });
|
当 abort() 被调用时,这个 fetch() promise 将 reject 一个名为 AbortError 的 DOMException。
取消之后,你会发现控制台报错了,因为 fetch promise 已经 reject 了 AbortError。
如果不想看到这个错误,可以通过 try-catch
将 fetch
包裹起来,在 catch 中打印错误即可。
axios
https://www.axios-http.cn/docs/cancellation
在低版本中的 axios v0.22.0
中,可以通过它本身提供的 cancelToken
来控制请求取消。高版本中已废弃
同理 fetch,使用 AbortController
控制请求取消。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| import axios from "axios";
let _env = import.meta.env
let url = _env.MODE == 'development'?_env.VITE_APP_BASE_API:_env.VITE_HOST_URL
const service = axios.create({ baseURL:url, timeout:5000, })
const ac = new Map()
service.interceptors.request.use( (config) => {
if (ac.get(config.url)) { ac.get(config.url).abort() ac.delete(config.url) }
const c = new AbortController() config.signal = c.signal ac.set(config.url, c)
return config }, (error) => { return Promise.reject(error) } )
service.interceptors.response.use((response) => { const { success, message, data } = response.data
ac.delete(config.url)
if (success) { return data } else { return Promise.reject(new Error(message)) } })
export default service
|
过渡 CancelToken deprecated
此 API 从 v0.22.0 开始已被弃用,不应在新项目中使用。
可以使用 CancelToken.source 工厂方法创建一个 cancel token ,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const CancelToken = axios.CancelToken; const source = CancelToken.source();
axios .get('/user/12345', { cancelToken: source.token }) .catch(function (thrown) { if (axios.isCancel(thrown)) { console.log('Request canceled', thrown.message); } else { } });
axios.post('/user/12345', { name: 'new name' }, { cancelToken: source.token })
source.cancel('Operation canceled by the user.');
|
在过渡期间,您可以使用这两种取消 API,即使是针对同一个请求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| const controller = new AbortController();
const CancelToken = axios.CancelToken; const source = CancelToken.source();
axios.get('/user/12345', { cancelToken: source.token, signal: controller.signal }).catch(function (thrown) { if (axios.isCancel(thrown)) { console.log('Request canceled', thrown.message); } else { } });
axios.post('/user/12345', { name: 'new name' }, { cancelToken: source.token })
source.cancel('Operation canceled by the user.');
controller.abort();
|