React Query:离线恢复时如何避免依赖Mutation竞态并保证同步顺序?
解决离线同步时Mutation的顺序执行问题
问题场景
我有两个需按顺序执行的Mutation:
- 创建草稿文章
- 提交草稿文章
必须先完成草稿创建,才能执行最终提交。离线状态下可本地执行这两个操作,后续同步到后端。但恢复在线且未关闭应用时,自动同步过程中可能出现第二个Mutation先于第一个完成的情况,导致业务错误。而重启应用后,queryClient.resumePausedMutations会按顺序同步Mutation,第二个会等待第一个完成,此场景下无问题。
解决方案
1. 绑定Mutation的触发顺序
不要在离线时同时触发两个Mutation,而是将提交草稿的操作绑定到创建草稿Mutation的onSuccess回调中。这样无论在线还是离线,只有当第一个Mutation(本地或后端执行)完成后,才会触发第二个Mutation,从根源上保证执行顺序。
示例代码:
// 创建草稿的Mutation const createDraft = useMutation({ mutationKey: ['create-draft'], mutationFn: (draftData) => api.createDraft(draftData), onSuccess: () => { // 草稿创建完成后触发提交操作 submitDraft.mutate(submitPayload); } }); // 提交草稿的Mutation const submitDraft = useMutation({ mutationKey: ['submit-draft'], mutationFn: (submitData) => api.submitDraft(submitData) }); // 离线/在线时仅触发第一步 const startWorkflow = () => { createDraft.mutate(draftPayload); };
2. 手动控制在线恢复时的同步顺序
如果必须在离线时同时记录两个Mutation,可以监听在线状态变化,手动按创建顺序逐个恢复同步:
useEffect(() => { const handleOnline = async () => { // 获取所有暂停状态的Mutation const pausedMutations = queryClient.getMutationCache().getAll().filter(mut => mut.state.status === 'paused'); // 按创建时间排序,保证先触发的先执行 const sortedMutations = pausedMutations.sort((a, b) => a.state.createdAt - b.state.createdAt); // 逐个执行,等待前一个完成再处理下一个 for (const mutation of sortedMutations) { await queryClient.resumePausedMutations({ mutationKey: mutation.options.mutationKey }); } }; window.addEventListener('online', handleOnline); return () => window.removeEventListener('online', handleOnline); }, [queryClient]);
3. 自定义Mutation队列处理逻辑
通过配置QueryClient的MutationCache队列,强制所有Mutation按创建顺序执行:
const queryClient = new QueryClient({ mutationCache: new MutationCache({ queue: { process: async (mutations) => { // 按创建时间排序后逐个执行 for (const mut of mutations.sort((a, b) => a.state.createdAt - b.state.createdAt)) { await mut.execute(); } } } }) });
这种方式会全局控制所有Mutation的执行顺序,确保不会出现乱序完成的情况。
内容的提问来源于stack exchange,提问作者jligeza
相关产品推荐
相关产品推荐

