← 中文资源

简体中文版本

Node.js 中 AbortController 信号对 fetch 无效

通过正确传递 signal 并区分连接阶段与读取阶段的取消,修复未被取消的 fetch 调用。

阅读英文原文

症状

对 AbortController 调用 abort 似乎毫无作用:fetch 的 Promise 仍会 resolve 或继续挂起,请求在网络上继续。signal 存在但常常没有转发进客户端选项,或 abort 在响应对象返回之后、body 仍在读取时触发,于是取消落在不再被观察的阶段。

诊断

用最小示例确认 fetch 的 catch 能打印 AbortError;在读取 body 时触发 abort 观察行为;搜索包装层是否透传 signal。

node -e "const c=new AbortController(); fetch(url,{signal:c.signal}).catch(e=>console.log(e.name)); c.abort()"

根因

AbortSignal 从未到达底层请求,或 abort 发生在客户端不再视为可取消的阶段,因此尽管调用了 abort,请求仍在继续。

修复

把 signal 贯穿所有构造请求的层:直接调用、重试包装与辅助函数。把超时绑定到同一个 controller,使取消与过期共用一条路径,并明确响应头到达后是否仍可取消。

验证

触发 abort 确认请求迅速以 AbortError 拒绝,再确认对端停止接收该请求的数据。客户端拒绝与服务端停止共同证明取消生效。

常见陷阱

把 signal 传给自定义客户端却没实现取消支持,会造成“看似取消实则继续”;需确认底层确实尊重 signal。