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

RxJS Subscribe无响应问题:API返回200但未进入回调

问题分析与解决方案

核心原因

你的问题本质是异步操作与组件销毁的时序冲突:

  • goBack() 调用 generateCode() 后,立刻执行 this.router.navigate(["/home"]),直接触发当前组件卸载。
  • generateCode() 中的 getOpportunityCount API 请求是异步的,而你用了 untilDestroyed(this) 操作符——这个操作符会在组件销毁时自动取消所有关联的订阅,导致API返回200后,回调函数根本没机会执行。

另外原代码还有一个逻辑漏洞:生成 offerCode 的代码是同步执行的,会在API返回前就运行,此时 this.countNewOffers 还未被赋值,即使API正常返回,也会先存入错误的offerCode到localStorage。

修复方案

1. 改造 generateCode,让它返回Observable

将异步逻辑包装成Observable,确保我们能等待它执行完成:

import { of, Observable, tap, catchError } from 'rxjs';

generateCode(): Observable<void> {
  if (!navigator.onLine) {
    this.loading = false;
    return of(void 0);
  }

  this.customerId = localStorage.getItem(LocalstorageKeyEnum.SELECTED_CUSTOMER)
    ? JSON.parse(localStorage.getItem(LocalstorageKeyEnum.SELECTED_CUSTOMER)).id
    : "NEW";

  if (this.customerId === "NEW") {
    this.countNewOffers = 1;
    const offerCode = `OF-${this.customerId}-${this.countNewOffers}`;
    this.offer.code = offerCode;
    localStorage.setItem(LocalstorageKeyEnum.OFFER, JSON.stringify(this.offer));
    this.loading = false;
    return of(void 0);
  } else {
    this.loading = true;
    return this.offerService.getOpportunityCount(this.customerId)
      .pipe(
        untilDestroyed(this),
        tap((data) => {
          this.loading = false;
          this.countNewOffers = data + 1;
          const offerCode = `OF-${this.customerId}-${this.countNewOffers}`;
          this.offer.code = offerCode;
          localStorage.setItem(LocalstorageKeyEnum.OFFER, JSON.stringify(this.offer));
        }),
        catchError((error) => {
          this.loading = false;
          this.countNewOffers = error.status === 404 ? 1 : undefined;
          const offerCode = `OF-${this.customerId}-${this.countNewOffers || "NEW"}`;
          this.offer.code = offerCode;
          localStorage.setItem(LocalstorageKeyEnum.OFFER, JSON.stringify(this.offer));
          return of(void 0);
        })
      );
  }
}

2. 修改 goBack,等待异步操作完成后再导航

用 switchMap 确保 generateCode 的异步逻辑执行完毕,再执行后续的产品移除和导航:

goBack() {
  this.generateCode()
    .pipe(
      switchMap(() => this.offerService.removeAllSelectedProducts(this.offer.products)),
      filter((removedProducts) => removedProducts)
    )
    .subscribe(() => this.router.navigate(["/home"]));
}

额外排查点

如果修改后仍有问题,检查以下内容:

  • 确认组件类上添加了 @UntilDestroy() 装饰器(如果使用的是 @ngneat/until-destroy 库),否则 untilDestroyed(this) 不会生效。
  • 检查 getOpportunityCount 的API响应格式是否符合预期,比如是否返回的是纯数字而非包裹在对象中的数字(Swagger返回正常但前端解析异常的情况也可能出现)。

内容的提问来源于stack exchange,提问作者Jack23

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 07:15:34