【问题标题】:Subscription still live after the parameter changed参数更改后订阅仍然有效
【发布时间】:2021-09-08 15:22:46
【问题描述】:

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

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

【问题讨论】:

  • 使用后退订。

标签: angular rxjs subscription angular11


【解决方案1】:

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

您需要使用像 swithcMap 这样的高阶映射运算符将一个可观察对象映射到另一个对象,并使用带有参数 1take 运算符在第一次发射后关闭第一个可观察对象。

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
  }
);

【讨论】:

  • 如果路由参数容易发生变化并且需要检测变化,则需要删除take(1)逻辑。此外,我们真的不应该将逻辑放在任何 Observable 的订阅回调中。一切都在pipe!最后,我不鼓励修改 switchMap 函数中的局部变量:那些应该真正进入 tap 以保持事物整洁和易于维护。
  • @WillAlexander:大多数观点都需要解释。为什么不在订阅回调中加入逻辑呢?与在tap 中执行用于副作用的逻辑相比,它更干净。 “一切都在pipe” - 为什么?你的意思是说有一个空的subscribe 总是更好?为什么?此外,大多数情况下,路由的第一次发射就足够了,因为稍后路由到同一页面将触发带有自己参数的单个订阅。
  • @MichaelD 谢谢你,它工作得很好,但出现了另一个问题
  • OP:@WillAlexander 关于使用takeUntil 关闭订阅的观点对于避免在组件被销毁后打开订阅也很重要。请在此处查看更多信息:stackoverflow.com/a/60223749/6513921
  • 但是@WillAlexander 的评论解决了这个问题,谢谢大家
【解决方案2】:

这是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)。

【讨论】:

    猜你喜欢
    • 2017-09-10
    • 1970-01-01
    • 2014-03-30
    • 1970-01-01
    • 2019-07-21
    • 2023-03-05
    • 1970-01-01
    • 2020-06-03
    • 1970-01-01
    相关资源
    最近更新 更多