表单重复提交时用AbortController取消上一次请求:先abort旧控制器,再新建并绑定signal,保存引用至组件属性或闭包,完成后清空引用防误调;适用于fetch、XHR等所有支持AbortSignal的异步操作。

在表单重复提交场景中,用 AbortController 取消上一次未完成的请求,核心是:每次提交前调用上一个控制器的 abort(),再新建控制器并绑定到新请求。
保存 AbortController 实例引用
不能每次请求都新建且丢弃控制器,必须保留对上一次控制器的引用,才能主动中止它。通常存在组件实例属性或闭包变量中:
- 在类组件中,可挂载为
this.abortController - 在函数组件中,可用
useRef(React)或闭包变量(原生 JS)持久化引用 - 务必在 abort 后重置引用(如设为
null),避免调用已 abort 的控制器的abort()报错
提交时先中止再发起新请求
表单提交事件处理函数中,按固定顺序执行:
- 检查是否存在上一个控制器,有则调用
.abort() - 新建
AbortController,保存其signal到fetch选项 - 更新控制器引用,指向新实例
示例(原生 JS):
let abortController = null;
async function handleSubmit(event) {
event.preventDefault();
// 中止上一次请求(如果存在)
if (abortController) {
abortController.abort();
}
// 创建新控制器
abortController = new AbortController();
try {
const res = await fetch('/api/submit', {
method: 'POST',
body: new FormData(event.target),
signal: abortController.signal // 绑定信号
});
console.log('提交成功', await res.json());
} catch (err) {
if (err.name === 'AbortError') {
console.log('请求已被取消');
} else {
console.error('请求失败', err);
}
}
}
注意请求完成后的清理
请求成功或失败后,控制器无需手动销毁,但建议在 finally 或响应处理完毕后清空引用,防止内存泄漏或误 abort:
- 在
try/catch/finally的finally块中设abortController = null - 若使用
useRef(React),可在useEffect清理函数中 abort,并在请求结束时重置 ref - 避免在 abort 后再次调用
abort(),会抛出InvalidStateError
适用于所有基于 signal 的异步操作
AbortController 不限于 fetch,也支持 XMLHttpRequest(需手动监听 abort 事件)、setTimeout 封装、甚至自定义 Promise(通过 signal.addEventListener('abort'))。只要操作接受 AbortSignal,就能统一控制生命周期。











