DEBUG.WIKI
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →
雨云;给项目一台云服务器
晚安云;香港 CN2 ¥15/月

RTK Query 配置 timeout 后,主动取消报 Illegal invocation

Redux Toolkit 2.7.0在timeout分支把AbortController.abort直接登记为事件回调,主动取消可能抛Illegal invocation且底层请求继续。核对包含修正的依赖,并分别验证取消和自然超时。

给 RTK Query 的 fetchBaseQuery 配上 timeout 后,主动取消一个仍在进行的 mutation,浏览器却报:

TypeError: Failed to execute 'abort' on 'AbortController': Illegal invocation

在 Redux Toolkit 2.7.0 的这条路径中,取消结果可能已经返回给调用方,底层 fetch 却没有随之中止。这与“服务端处理太慢,增加 timeout 即可”是不同问题:失败发生在转发取消信号的回调里。

timeout 分支把原生方法当成普通回调

2.7.0 在配置了非零 timeout 时创建内部 AbortController,并用下面的方式监听外层信号:

api.signal.addEventListener('abort', abortController.abort);

原生 abort 方法需要以所属的 AbortController 为接收者。作为事件监听器直接调用时,接收者不再是这个控制器,浏览器会拒绝调用;内部控制器因而没有在这次主动取消中被中止。

没有进入 timeout 分支的请求,或由另一个自定义 baseQuery 发出的请求,不应直接套用这个解释。先确认实际安装版本、该 endpoint 最终使用的 baseQuery、timeout 来源及完整堆栈。不要为诊断输出认证头或上传正文。

应用外层把 promise.abort() 再包一层箭头函数,也不能修掉库内部已经登记的错误监听器。全局替换 AbortController 或吞掉 Illegal invocation 只会让异常不再明显,不能证明底层请求已取消。

更新实际使用的 Toolkit,不撤掉请求时限

截至 2026 年 10 月 25 日,正式 Redux Toolkit 2.13.0 的 fetchBaseQuery 已不再使用上述裸方法监听方式。它将调用方信号与超时信号组合;内部转发通过箭头回调调用控制器,并保留取消原因。

这能确认 2.13.0 包含相应处理,不意味着所有 2.x 都受影响,也不据此指定最早修复版本。项目应沿现有兼容升级方案选择包含修正的正式版本,检查锁文件和部署产物实际解析的 @reduxjs/toolkit,保留已有认证、序列化及错误处理配置。

把 timeout 删除或改为零,会撤掉这层请求时限;它可能暂时避开旧分支,但也可能使原本有截止时间的请求长期等待,不适合当成默认修复。若业务使用自定义 fetchFn,还要确认它真正消费收到的 Request 信号,而不是另起一个丢失 signal 的请求。

分别验收主动取消与自然超时

在受控、无副作用的慢响应入口验证两个独立场景:主动调用原 mutation 结果上的 abort,以及不主动取消、等待配置时限。前者不应再出现 Illegal invocation,底层网络请求应收到取消;后者应走原来的超时错误处理,不能因为修主动取消而失去时限。

还要检查取消后界面的 loading、错误提示和下一次正常调用。仅看到 RTK Query 的 promise 已 rejected,不能单独证明网络传输已经停止;浏览器网络记录和受控服务端记录能帮助区分这两层结果。

取消 fetch 不等于撤销服务端已经执行的操作。对上传、支付或创建数据的请求,若结果不明,仍按业务身份查询实际状态,不因出现取消错误就立即重发。升级依赖解决的是取消信号传递,不能代替事务或幂等性约定。