React-Query中嵌套循环链式调用Mutation的问题排查及最优实现
问题原因
你遇到的问题确实和React-Query的mutation默认行为有关:同一个useMutation实例默认只允许存在一个活跃的请求,当新的请求发起时,会自动取消之前未完成的同实例请求。
你的代码中所有pattern的创建都复用了同一个createPatternMutation实例,当两个puzzle的创建请求几乎同时完成时,第二个puzzle触发的pattern创建请求会取消第一个puzzle的pattern请求,最终只有第二个puzzle的pattern接口被调用。
解决方案
通过为createPatternMutation设置动态的mutationKey,让每个pattern请求(或至少每个puzzle下的pattern请求)拥有独立的标识,React-Query就会将它们视为不同的mutation任务,允许并发执行。
修改createPatternMutation的定义:
const createPatternMutation = useMutation( ({puzzleId, body}) => createPattern(puzzleId, body), { // 根据puzzleId和pattern名称生成唯一的mutationKey mutationKey: (variables) => ['create-pattern', variables.puzzleId, variables.body.pattern_name] } );
如果不需要区分到单个pattern,仅区分到puzzle级别也可以,这样同一个puzzle下的pattern会共享一个mutationKey,但不同puzzle的不会冲突:
const createPatternMutation = useMutation( ({puzzleId, body}) => createPattern(puzzleId, body), { mutationKey: (variables) => ['create-pattern', variables.puzzleId] } );
额外优化建议
- 可以在mutation中添加错误处理,避免单个pattern创建失败影响整个流程:
const patternsMutations = puzzle.patterns.map((pattern) => createPatternMutation.mutateAsync({ puzzleId: data.data.id, body: {...pattern} }).catch(err => { console.error(`创建pattern ${pattern.pattern_name}失败`, err); }) );
- 如果需要严格保证puzzle和pattern的创建顺序(比如先完成第一个puzzle的所有pattern再创建第二个puzzle),可以将并发执行改为串行执行:
// 串行处理每个puzzle for (const puzzle of puzzles) { const puzzleData = await createPuzzleMutation.mutateAsync({body: {name: puzzle.puzzle_name}}); const patternsMutations = puzzle.patterns.map(pattern => createPatternMutation.mutateAsync({ puzzleId: puzzleData.data.id, body: {...pattern} }) ); await Promise.allSettled(patternsMutations); }
内容的提问来源于stack exchange,提问作者complexSandwich
相关产品推荐
相关产品推荐

