RTK Query乐观UI场景:是否应将try-catch放入for循环?
问题解决思路与代码修正
你的核心问题有两个:一是patchResult的作用域导致外部无法访问,二是原代码仅能处理最后一次乐观更新的回滚,漏掉了循环中其他的更新操作。
不建议直接将try-catch移入循环的原因
把try-catch放进循环里虽然能解决作用域问题,但存在两个明显缺陷:
queryFulfilled是当前请求的唯一Promise,多次await它完全没必要,只会重复等待同一个结果- 无法保证所有乐观更新的原子性:如果请求失败,你需要回滚所有已做的乐观更新,而不是单个
更合理的解决方案:收集所有patch结果,统一处理回滚
先把循环中每次生成的patchResult存入数组,在请求失败时遍历数组执行所有回滚操作,这样既能解决作用域问题,又能保证所有乐观更新的一致性。
修正后的代码如下:
async onQueryStarted({ user_id }, { dispatch, queryFulfilled, getState }) { // 收集所有乐观更新的patch结果 const patchResults = []; for (const { endpointName, originalArgs } of Api.util.selectInvalidatedBy(getState(), [{ type: 'USER'}])) { const patchResult = dispatch( UserApi.util.updateQueryData('users', originalArgs, (draft) => { return { ...draft, user: { ...draft.user, is_follow: !draft.user.is_follow } } }) ); patchResults.push(patchResult); } try { await queryFulfilled; } catch { // 请求失败时,回滚所有乐观更新 patchResults.forEach(patch => patch.undo()); } }
额外说明
Api.util.selectInvalidatedBy返回的是所有需要失效的端点,你需要确保这些端点的updateQueryData逻辑是正确的,避免更新错误的数据- 这种统一收集、统一回滚的方式,符合RTK Query乐观UI的设计思想,能保证数据的一致性
内容的提问来源于stack exchange,提问作者localdata01
相关产品推荐
相关产品推荐

