abortcontroller 可中止 fetch 请求,但分片下载校验需在请求、流读取、哈希计算、校验比对等每个环节主动监听 signal.aborted 并退出,同时清理定时器、web worker、blob 等资源,推荐封装为带 abort 方法的 promise 工具函数。

AbortController 可以用来中止 fetch 请求,但分片下载校验任务通常包含多个异步阶段(如:发起请求、读取流、计算哈希、比对校验值),单纯 abort fetch 并不能自动停止后续的流处理或计算逻辑。要真正终止整个任务,需在每个关键环节主动监听 signal.aborted 并及时退出。
1. 创建 AbortController 并传入 fetch 与流处理链路
初始化控制器后,把 signal 同时用于 fetch 和后续的 ReadableStream 消费逻辑中:
示例片段:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
const controller = new AbortController();
const { signal } = controller;
// 发起分片请求(带 signal)
const response = await fetch(url, { signal });
// 获取流并手动消费,每一步都检查 signal
const reader = response.body.getReader();
let chunks = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
if (signal.aborted) {
reader.cancel('Download aborted');
throw new Error('Download cancelled by user');
}
chunks.push(value);
}
2. 在哈希计算中定期检查 signal(尤其大文件)
使用 SubtleCrypto.digest() 计算整个分片哈希时,若先拼接所有 chunk 再计算,会阻塞主线程且无法中断。应改用流式哈希(如分块调用 hasher.update()),并在每次 update 后检查 signal:
- 用
crypto.subtle.importKey()+crypto.subtle.digest()不支持中断,需自行实现增量哈希逻辑 - 推荐使用成熟库如 web-streams-polyfill 或封装
TransformStream做可中断哈希流 - 简易做法:循环处理每个 chunk 时加
if (signal.aborted) throw ...
3. 校验失败或用户取消时统一清理资源
不只是中止网络请求,还要确保:
- 已启动的
setTimeout或轮询校验定时器被clearTimeout清除 - 正在运行的 Web Worker(如果用它做哈希)收到
postMessage({ type: 'abort' })并自行退出 - 临时创建的
Blob或URL.createObjectURL被及时释放(调用URL.revokeObjectURL)
4. 封装成可取消的 Promise 工具函数
把分片下载 + 校验封装为返回 Promise 的函数,并暴露 abort() 方法:
function downloadAndVerify(url, expectedHash, options = {}) {
const controller = new AbortController();
const { signal } = controller;
const task = (async () => {
const response = await fetch(url, { signal });
const reader = response.body.getReader();
const hasher = new SHA256(); // 假设你有流式哈希实例
while (true) {
const { done, value } = await reader.read();
if (done) break;
if (signal.aborted) throw new Error('Aborted during read');
hasher.update(value);
}
const actualHash = await hasher.digest();
if (signal.aborted) throw new Error('Aborted before verification');
if (!equalHash(actualHash, expectedHash)) {
throw new Error('Hash mismatch');
}
return { ok: true };
})();
return {
promise: task,
abort: () => controller.abort()
};
}
// 使用:
const job = downloadAndVerify('/part1.bin', 'a1b2...');
job.promise.catch(err => console.error(err));
// 随时调用:
job.abort();
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










