AbortController是一个Web API,它提供了一个信号对象(AbortSignal),该对象可以用来取消与Fetch API相关的操作。
使用方法:
1. 创建AbortController实例
const controller = new AbortController();
2. 获取AbortSignal对象
const signal = controller.signal;
3.fetch请求或axios请求中取消请求
const controller = new AbortController();
fetch(url, { signal:controller.signal }).then(response => {
// 处理响应数据
}).catch(error => {
if (error.name === 'AbortError') {
console.log('Fetch 请求已被取消');
} else {
// 处理其他错误
}
});
controller.abort();
const controller = new AbortController();
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// 取消请求
controller.abort()
实战
使用 express 快速搭建一个服务
// npm init
// npm i express
let express = require("express");
const app = express();
// express@4.xx
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.all("", function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type");
res.header("Access-Control-Allow-Methods", "*");
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
// 定义一个GET路由: 模拟网络请求不稳定场景
app.get("/getUser", (req, res) => {
console.log("get---query", req.query);
setTimeout(() => {
res.send({
code: 0,
msg: "get请求成功",
data: req.query,
});
}, 3000);
});
// 监听3000端口
app.listen(3000, () => {
console.log("Server is running on port 3000");
});
封装axios请求 /utils/request.js
import axios from 'axios'
const instance = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
// baseURL: '/',
// 超时
timeout: 100000
})
// 存储需要被取消的控制器 key:url value:AbortController实例
const abortControllerMap = new Map()
// request拦截器
instance.interceptors.request.use(
(config) => {
// 省略其他配置....
// 对于需要被取消的请求进行处理
if (config.enableAbort) {
const abortController = abortControllerMap.get(config.url)
abortController && abortController.abort()
const controller = new AbortController()
config.signal = controller.signal
abortControllerMap.set(config.url, controller)
}
return config
},
(error) => {
console.log(error)
Promise.reject(error)
}
)
instance.interceptors.response.use(
(res) => {
// 释放已发送完毕的请求
abortControllerMap.delete(res.config.url)
return res
},
(err) => {
console.error('err', err)
}
)
export default instance
新建业务api api/about.js
import request from '@/utils/request'
// 模拟一个需要被取消的请求
export const getUserApi = (data) => {
return request.get('/api/getUser', {
params: data,
enableAbort: true
})
}
实际业务页面去调用
<template>
<div class="about">
<h1>This is an about page</h1>
<input type="text" @input="onInput" v-model="keyWord" />
</div>
</template>
<script setup>
import { ref } from 'vue'
import { getUserApi } from '@/api/about.js'
const keyWord = ref('')
const onInput = async () => {
const res = await getUserApi({ keyWord: keyWord.value })
console.log('res', res)
}
</script>