解决Apollo Link中间件重试请求后无法正确返回结果的问题
问题分析
你的代码核心问题在于:第一次请求的订阅会在响应返回后(即使触发了重试逻辑),最终调用observer.complete(),导致整个Observable提前结束。而重试请求的响应还未返回时,下游链路已经认为请求完成,自然收不到重试后的结果。
修复方案
修改重试逻辑,在触发重试时先取消初始请求的订阅,同时确保重试请求的所有事件(next/error/complete)都正确传递给observer:
export const handlerVersionMismatch: ApolloLink = new ApolloLink( (operation: Operation, forward: NextLink) => { return new Observable<FetchResult>((observer) => { let retry = true; let currentSubscription: Subscription | null = null; const executeOperation = (op: Operation) => { currentSubscription = forward(op).subscribe({ next: (response) => { if (retry && handleVersionMismatch(response)) { // 取消当前订阅,避免触发complete干扰 currentSubscription?.unsubscribe(); retry = false; // 克隆operation并更新版本,遵循Apollo操作对象不可变的设计 const newOperation = op.clone({ variables: { ...op.variables, version: response.data?.cart?.version } }); executeOperation(newOperation); } else { observer.next(response); observer.complete(); } }, error: (err) => observer.error(err), complete: () => { // 仅在无需重试时触发complete,避免提前结束Observable if (!retry) observer.complete(); } }); }; executeOperation(operation); return () => { currentSubscription?.unsubscribe(); }; }); }, );
关键改动说明
- 新增
currentSubscription跟踪当前活跃请求,触发重试时立即取消旧订阅,防止旧请求的complete事件提前终止整个流。 - 使用
operation.clone()创建新操作对象修改版本变量,避免污染原Operation实例(Apollo官方推荐操作对象保持不可变)。 - 调整complete事件触发时机:只有在正常响应无需重试,或者重试请求完成时,才调用
observer.complete(),确保下游链路能等待到重试后的结果。 - 封装
executeOperation函数,简化重试逻辑的代码复用。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

