用 abortcontroller 终止大文件流式传输,需将 signal 传给 fetch 并在 reader.read() 后主动检查 signal.aborted,若为 true 则调用 reader.cancel() 并抛出 aborterror;取消按钮触发 controller.abort() 即可。

用 AbortController 终止大文件流式传输,核心是把它的 signal 传给 fetch 请求,并在读取响应流(response.body)时监听中断信号。关键在于:流式读取本身不会自动响应中止,必须手动在每次 reader.read() 后检查 signal.aborted,并主动跳出循环或抛出错误。
1. 创建控制器并发起带 signal 的 fetch 请求
这是起点。确保请求本身支持中止 —— fetch 是目前唯一原生支持 AbortSignal 的网络 API:
const controller = new AbortController();
const { signal } = controller;
// 发起流式请求(如下载大文件)
const response = await fetch('/large-file.zip', { signal });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
// 确保响应体是 ReadableStream(通常默认就是)
const reader = response.body.getReader();
2. 在流读取循环中主动检查中止状态
reader.read() 不会自动感知 signal 中止,必须显式判断。一旦 signal.aborted 为 true,应立即停止读取并清理:
- 调用
reader.cancel()通知流终止内部操作 - 可选:抛出
new DOMException('Aborted', 'AbortError')保持语义一致性 - 避免继续处理已中止的 chunk 或触发后续逻辑
示例读取逻辑:
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
// 处理 chunk(如写入 Blob、解压、进度更新等)
processChunk(value);
// ⚠️ 关键:每次读取后检查是否被中止
if (signal.aborted) {
await reader.cancel(); // 清理流
throw new DOMException('Download aborted', 'AbortError');
}
}
} catch (err) {
if (err.name === 'AbortError') {
console.log('传输已由用户取消');
} else {
console.error('读取流失败:', err);
}
}
3. 提供外部取消能力(如按钮点击)
把 controller.abort() 暴露给用户交互,比如绑定到「取消」按钮:
document.getElementById('cancel-btn').addEventListener('click', () => {
controller.abort(); // 触发 signal.aborted = true
});
注意:调用 abort() 后,所有监听该 signal 的地方(包括 fetch 内部)都会收到通知,但流读取循环仍需按第 2 步主动响应。
4. 配合流式处理工具链时的注意事项
如果使用 TransformStream、WritableStream 或第三方库(如 web-streams-polyfill),要确保整个管道能响应中止:
- 自定义
transform()中也应定期检查signal.aborted - 向
writable.getWriter()写入前,先确认 signal 未中止 - Polyfill 环境下,部分旧版浏览器不支持
ReadableStream.prototype.cancel,需降级处理(如直接丢弃后续 chunk)
不复杂但容易忽略:中止不是“暂停”,它不可逆;一旦 abort,signal 就永久处于中止状态,不能复用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











