参数更改后订阅仍然有效

Subscription still live after the parameter changed

我有一个订阅来获取路由附带的参数,在该订阅中(成功后)我正在从同一服务调用另一个订阅以获取消息详细信息。 问题是:当参数更改时,与旧参数相关的订阅仍然存在。

this.routes.params.subscribe(param => {
        this.isLoading = true;
        this.messageId = param['id'];
        this.inboxService.getMessageDetail(toNumber(this.messageId)).subscribe((dat) => {
          this.initMessageDetails(dat);
        })
      })

这就是不鼓励嵌套订阅的确切原因。它会导致多个订阅,其中一些可能未关闭。

您需要使用更高阶的映射运算符,例如带有参数 1swithcMap to map from one observable to another and take 运算符,以在首次发射后关闭第一个 observable。

import { take, switchMap } from 'rxjs/operators';

this.routes.params.pipe(
  take(1),                // <-- complete after first emission
  switchMap(param => {    // <-- map to another observable
    this.isLoading = true;
    this.messageId = param['id'];
    return this.inboxService.getMessageDetail(toNumber(this.messageId));
  }
).subscribe(
  (dat) => {
    this.initMessageDetails(dat);
  },
  (error: any) => {
    // handle errors
  }
);

这是 switchMap 运算符的完美用例!它为父级的每个发射订阅子 Observable,取消订阅该子 Observable 的先前实例。

只要有可能,您应该避免在 subscribe 回调中放置逻辑,尤其是当它涉及订阅另一个 Observable 时。使用 RxJS Observables 时,使用它们的 pipe 运算符:

this.routes.params.pipe(
  tap(params => {
    this.isLoading = true;
    this.messageId = params['id'];
  }),
  switchMap(params => this.inboxService.getMessageDetail(toNumber(this.messageId))),
  tap(dat => this.initMessageDetails(dat))
).subscribe();

您还应该实现某种取消订阅逻辑,以确保您的 Observable 在组件关闭时关闭(例如,使用 takeUntil 运算符和在 ngOnDestroy() 中发出的 Subject)。 =16=]