js中AbortController请求中止的实现
一、介绍
AbortController 是 JavaScript 提供的一个强大工具,它允许开发者中止一个或多个 Web 请求。这个 API 最初是为了 fetch 请求设计的,但现在已经被许多其他浏览器 API 和第三方库所采用。
AbortController 的主要用途包括
- 取消不再需要的
fetch请求; - 清理长时间运行的操作;
- 实现请求超时;
- 处理组件卸载时的资源清理;
二、基本使用
2.1 创建 AbortController
const controller = new AbortController(); const signal = controller.signal;
2.2 与 fetch 结合使用
const controller = new AbortController();
const signal = controller.signal;
fetch("https://api.example.com/data", { signal })
.then((response) => response.json())
.then((data) => console.log(data))
.catch((err) => {
if (err.name === "AbortError") {
console.log("请求被中止");
} else {
console.error("请求错误:", err);
}
});
// 在需要时中止请求
controller.abort();
三、常用场景
3.1 用户触发的取消
const controller = new AbortController();
const fetchButton = document.getElementById("fetch-button");
const cancelButton = document.getElementById("cancel-button");
fetchButton.addEventListener("click", () => {
fetch("https://api.example.com/data", { signal: controller.signal }).then(/* ... */).catch(/* ... */);
});
cancelButton.addEventListener("click", () => {
controller.abort();
});
3.2 请求超时
function fetchWithTimeout(url, options, timeout = 5000) {
const controller = new AbortController();
const signal = controller.signal;
// 设置超时
const timeoutId = setTimeout(() => controller.abort(), timeout);
return fetch(url, { ...options, signal }).finally(() => clearTimeout(timeoutId));
}
fetchWithTimeout("https://api.example.com/data", {}, 3000)
.then(/* ... */)
.catch((err) => {
if (err.name === "AbortError") {
console.log("请求超时");
}
});
3.3 React 组件卸载时取消请求
import { useEffect, useState } from "react";
function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
const controller = new AbortController();
fetch("https://api.example.com/data", { signal: controller.signal })
.then((response) => response.json())
.then(setData)
.catch((err) => {
if (err.name !== "AbortError") {
console.error("获取数据失败:", err);
}
});
return () => controller.abort();
}, []);
return <div>{data ? JSON.stringify(data) : "加载中..."}</div>;
}
3.4 并行请求的统一取消
const controller = new AbortController();
const signal = controller.signal;
const requests = [fetch("/api/data1", { signal }), fetch("/api/data2", { signal }), fetch("/api/data3", { signal })];
Promise.all(requests)
.then(/* 处理所有响应 */)
.catch((err) => {
if (err.name === "AbortError") {
console.log("所有请求已被取消");
}
});
// 取消所有请求
controller.abort();
四、高级细节
4.1 信号状态
signal.aborted 属性可以检查信号是否已被中止:
const controller = new AbortController(); console.log(controller.signal.aborted); // false controller.abort(); console.log(controller.signal.aborted); // true
4.2 事件监听
可以监听 abort 事件:
const controller = new AbortController();
controller.signal.addEventListener("abort", () => {
console.log("请求被中止");
});
controller.abort();
4.3 重用与限制
一个 AbortController 只能中止一次,之后就不能再使用了:
const controller = new AbortController(); controller.abort(); controller.abort(); // 第二次调用不会有任何效果
如果需要多次中止操作,需要创建新的 AbortController 实例。
4.4 与其他 API 集成
除了 fetch,AbortController 还可以用于其他 API:
// Web APIs
const videoStream = await navigator.mediaDevices.getUserMedia({
video: true,
signal: controller.signal
});
// Axios
const source = axios.CancelToken.source();
axios.get("/api/data", {
cancelToken: source.token
});
source.cancel();
4.5 自定义中止逻辑
你可以基于 AbortSignal 实现自己的可中止操作:
function doTask(signal) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => resolve("任务完成"), 5000);
signal.addEventListener("abort", () => {
clearTimeout(timer);
reject(new DOMException("任务被中止", "AbortError"));
});
if (signal.aborted) {
clearTimeout(timer);
reject(new DOMException("任务被中止", "AbortError"));
}
});
}
const controller = new AbortController();
doTask(controller.signal)
.then(console.log)
.catch((err) => {
if (err.name === "AbortError") {
console.log("任务被中止");
}
});
// 中止任务
controller.abort();
到此这篇关于js中AbortController请求中止的实现的文章就介绍到这了,更多相关js AbortController请求中止内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
关于js中removeEventListener取消事件监听的坑
许多入前端不久的人都会遇到removeEventListener无法清除监听的情况,下面这篇文章主要给大家介绍了关于js中removeEventListener取消事件监听的坑,文中通过实例代码介绍的非常详细,需要的朋友可以参考下2022-09-09


最新评论