自定义 hook 中自动处理请求取消的关键是将 abortcontroller 生命周期与组件挂载/卸载对齐:每次请求新建 controller,useeffect 清理函数调用 abort(),并用 useref 保存 controller 和 mounted 状态,确保响应到达前组件仍存活才更新状态。

在自定义 Hook 中自动处理请求取消,核心是把 AbortController 的生命周期与组件的挂载/卸载对齐:组件卸载时调用 abort(),避免状态更新到已销毁的组件上。
用 useEffect 清理函数绑定 abort
每次请求发起时创建新的 AbortController,将其 signal 传给 fetch 或其他支持 cancelable 的 API,并在 useEffect 的清理函数中调用 controller.abort():
- 清理函数会在组件卸载或下次 effect 执行前触发,天然适配取消时机
- 注意:不能复用同一个 controller 多次 —— 每次请求都应新建 controller
- 示例中把 controller 存在 ref 里,是为了在异步回调中安全访问 signal(避免闭包捕获过期 signal)
封装通用的 useRequest Hook
把取消逻辑内聚进一个可复用的 Hook,接收请求函数和依赖数组,返回 data/loading/error 和手动触发请求的方法:
- 内部用
useRef保存 controller,确保 cleanup 时能拿到最新实例 - 请求函数需接受
signal参数,并在 fetch/fetcher 中透传 - 手动触发(如点击按钮)时先 abort 上一次请求,再新建 controller 发起新请求
处理 Promise 状态更新前的竞态问题
即使请求被 abort,Promise 仍可能 resolve/reject(尤其使用 fetch 时 abort 会 reject),所以必须检查组件是否还“存活”才更新状态:
- 用
useRef标记 mounted 状态,在 effect 开始设为 true,cleanup 时设为 false - 在
then/catch中先判断mounted.current再调用setState - 不依赖
isCancelled或signal.aborted判断 —— 它们只说明请求是否被中止,不反映组件状态
兼容 Axios 等第三方库
Axios 原生支持 cancelToken(v0.22+ 推荐用 AbortController):
- 直接传
{ signal: controller.signal }给axios.get(..., { signal }) - 无需额外适配 —— Axios 内部会监听 abort 并 reject 请求 Promise
- 同样需要 mounted 检查,因为 reject 后仍会进入
catch分支
不复杂但容易忽略的是:取消不是“让请求停止发送”,而是“让后续响应不再生效”。关键在清理时机 + 状态更新守门,两者缺一不可。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











