如何在RTK-Query中间件中判断错误是否已在.catch()中处理?
问题解答
首先明确结论:无法直接在RTK-Query的中间件中判断mutation返回的Promise是否被调用了.catch()块。原因在于:
- RTK-Query派发的
/rejectedaction仅代表请求本身失败,它不追踪后续Promise链的执行逻辑(比如.then()/.catch()是否被调用)。Redux的action是请求状态的快照,和Promise的后续处理完全属于两个独立的运行时环节。
但可以通过以下几种替代方案实现类似需求:
方案1:给mutation调用添加自定义meta标记
在调用mutation时,通过options.meta传入一个自定义标志,告诉中间件是否需要跳过全局错误通知。业务代码中手动处理错误的场景,就带上这个标记:
// 调用mutation时,手动处理错误并跳过全局通知 const [mutateMyData] = useMyMutation(); mutateMyData(payload, { meta: { skipGlobalError: true } }).catch((err) => { // 业务侧自定义错误处理逻辑 console.error('手动处理错误:', err); }); // 全局错误中间件 const globalErrorMiddleware = (store) => (next) => (action) => { // 仅处理RTK-Query的rejected action,且没有标记跳过的情况 if (action.type.endsWith('/rejected') && !action.meta?.skipGlobalError) { // 展示全局错误通知 showNotification('请求失败:', action.error.message); } return next(action); };
方案2:利用mutation定义的onError配置
在定义RTK-Query的mutation时,通过onError字段指定该接口的自定义错误处理逻辑。中间件可以通过action的endpointName找到对应的endpoint配置,判断是否已有自定义错误处理,从而决定是否触发全局通知:
// 定义API时,给需要自定义处理的mutation添加onError const myApi = createApi({ baseQuery: fetchBaseQuery({ baseUrl: '/' }), endpoints: (builder) => ({ myMutation: builder.mutation({ query: (payload) => ({ url: '/data', method: 'POST', body: payload }), // 自定义错误处理 onError: (err) => { console.error('mutation自定义错误处理:', err); } }), anotherMutation: builder.mutation({ // 没有onError,交给全局中间件处理 query: (payload) => ({ url: '/other', method: 'POST', body: payload }) }) }) }); // 全局错误中间件 const globalErrorMiddleware = (store) => (next) => (action) => { if (action.type.endsWith('/rejected')) { const endpoint = myApi.endpoints[action.endpointName]; // 仅当endpoint没有定义onError时,触发全局通知 if (!endpoint.onError) { showNotification('请求失败:', action.error.message); } } return next(action); };
方案3:约定业务侧错误处理规范
如果团队能统一规范,可以约定:业务代码中如果手动处理了错误,就调用一个全局的markErrorHandled()方法(或者通过Redux状态标记),中间件检查这个状态再决定是否触发通知。不过这种方式依赖业务代码的执行顺序,不如前两种方案可靠。
内容的提问来源于stack exchange,提问作者bpGusar
相关产品推荐
相关产品推荐

