# AbortController

# 1、简介

AbortController 接口表示一个控制器对象,允许你根据需要中止一个或多个 Web 请求。

你可以使用 AbortController() 构造函数创建一个新的 AbortController 对象。使用 AbortSignal 对象可以完成与异步操作的通信。

# 2、基本信息

  1. 构造函数 AbortController(), 创建一个新的AbortController对象
  2. 实例属性 AbortController.signal, 返回一个AbortSignal对象,可以用它来和异步操作进行通信或者中止这个操作。
  3. 实例方法AbortController.abort(),中止一个尚未完成的异步操作。这能够中止 [fetch 请求]及任何响应体和流的使用。

# 3、fetch 示例

let controller;
const url = "video.mp4";

const downloadBtn = document.querySelector(".download");
const abortBtn = document.querySelector(".abort");

downloadBtn.addEventListener("click", fetchVideo);

abortBtn.addEventListener("click", () => {
  if (controller) {
    controller.abort();
    console.log("中止下载");
  }
});

function fetchVideo() {
  controller = new AbortController();
  const signal = controller.signal;
  fetch(url, { signal })
    .then((response) => {
      console.log("下载完成", response);
    })
    .catch((err) => {
      console.error(`下载错误:${err.message}`);
    });
}

# 4、AbortSignal

# 中止超时的读取操作

如果你需要中止一个超时的操作,你可以使用 AbortSignal.timeout() 静态方法。该方法返回一个在指定的毫秒时间后后自动超时的 AbortSignal

以下代码片段展示了如何成功地下载一个文件或者在五秒钟后处理一个超时的错误。注意,当出现超时时,fetch() promise 会以 TimeoutError DOMException 拒绝。这允许代码区分超时(可能需要通知用户)和用户手动中止操作。

const url = "video.mp4";
Ï
try {
  const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
  const result = await res.blob();
  // …
} catch (err) {
  if (err.name === "TimeoutError") {
    console.error("超时:获取结果的事件超过了 5 秒!");
  } else if (err.name === "AbortError") {
    console.error("Fetch 操作被用户中止(如浏览器停止按钮、关闭标签等)");
  } else {
    // 网络错误,或其他问题
    console.error(`错误:类型:${err.name},消息:${err.message}`);
  }
}

如果要从多个信号中中止,可以使用 AbortSignal.any()将它们合并为一个信号。

try {
  const controller = new AbortController();
  const timeoutSignal = AbortSignal.timeout(5000);
  const res = await fetch(url, {
    // 任意一个信号中止时,整个操作会被中止
    signal: AbortSignal.any([controller.signal, timeoutSignal]),
  });
  const body = await res.json();
} catch (e) {
  if (e.name === "AbortError") {
    // 通知用户操作中止
  } else if (e.name === "TimeoutError") {
    // 通知用户超时
  } else {
    // 网络错误,或其他问题
    console.log(`类型:${e.name},消息:${e.message}`);
  }
}
上次更新: 4/1/2025, 9:33:10 AM