You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 16:51:12