【问题标题】:how to subscribe to observable whose input depends on data from other observable如何订阅其输入依赖于其他可观察数据的可观察对象
【发布时间】:2019-07-07 05:27:01
【问题描述】:

在我的 Angular 应用程序中,我有一个组件,其数据取决于路由参数。 当页面第一次打开时数据被正确加载。当我切换到不同的页面但停留在同一个组件上(因此只有一个路由参数发生变化)时,不会加载新数据。

路由参数已更新,并且通过异步管道订阅的所有数据都已正确加载。然而,有一条数据需要额外处理。这个 observable 正在组件中被订阅。这是没有再次加载数据的那个。

在下面的代码中,内置的 paramMap 可观察订阅持续跟踪路由参数的更改并运行回调。第二个可观察的没有。我想这是因为第二个 observable 已完成,实际上被一个从未订阅过的新 observable 替换(在第一个回调中)。

如何最好地处理这个问题,同时从第二个 observable 中获取数据?

似乎使它起作用的唯一事情是将第二个订阅移动到第一个的回调。但这对我来说看起来不是很干净的代码,而且我不确定如果由于某种原因 observable 在被新代码替换时没有完成会发生什么。

ngOnInit(): void {
  this.route.parent.paramMap.subscribe((paramMap: ParamMap) => {
    this.id = paramMap.get('id');
    this.observable= this.service.getSomething(this.id);
  }
  this.observable.subscribe(
    // callback that handles the processing of the data
  )
}

【问题讨论】:

    标签: angular observable


    【解决方案1】:

    您可以在这里使用switchMap 运算符形式的 RxJS,例如:

    ngOnInit(): void {
        this.route.parent.paramMap.pipe(switchMap((paramMap: ParamMap) => {
          this.id = paramMap.get('id');
          return this.service.getSomething(this.id);
        })).subscribe(
            // callback that handles the processing of the data
          );
    }
    

    【讨论】:

      【解决方案2】:

      我可以想象你想做下面的事情(rxjs v6):

        ngOnInit(): void {
          this.route.parent.paramMap.pipe(
            map(paramMap: ParamMap) => this.id = paramMap.get('id'),
            mergeMap(id => this.service.getSomething(this.id))
          )
            .subscribe(
              // callback that handles the processing of the data
            )
        }
      

      所以每当参数发生变化时,整个管道都会被触发并调用服务。

      【讨论】:

        【解决方案3】:

        使用运算符:

        ngOnInit() {
          this.observable = this.route.parent.paramMap.pipe(
            map(paramMap => paramMap.get('id')),
            switchMap(id => this.service.getSomething(id))
          );
        }
        

        switchMap 将取消挂起的请求。

        如果您想让它们保持活跃,请使用mergeMap

        【讨论】:

        • 这是我在发布我的问题之前正在研究的确切解决方案,但我无法让它工作(通常是 observables 和 rxjs 的新手),因为我发现的示例使用的是使用运算符的旧样式.我仍然想知道如何正确退订。如果 observable 完成了就没有必要了,但是如果没有什么时候退订呢?
        • @YoNuevo 你可以随时取消订阅,我觉得最方便的是使用模板中的async 管道。我很少在我的组件代码中写.subscribe
        • 使用异步管道可以解决退订问题,但不幸的是,此订阅不可能(与此组件中使用的其他几个不同)。在大多数(如果不是全部)情况下,取消订阅是不必要的,因为 observable 将完成。但如果它没有然后路由参数发生变化,则再次运行 getSomething 并创建一个新的 observable。旧的会一直漂浮在某个地方还是取消 switchMap 会解决这个问题?
        • 不,路由的订阅将保留。如果您知道您将听多少次(firsttake(1) 等),请使用流量停止运算符,或者在您的 ngOnDestroy 函数中取消订阅。
        • 我解释(或理解)很差 :) 我不担心订阅路由,而是担心从 getSomething 返回的 observable。路由参数在完成之前发生变化的可能性很小,但并非不可能。如果发生这种情况并且 switchMap 中的代码再次被执行,getSomething 不会返回一个新的 observable 吗?原来的会怎样?它会被 switchMap 操作员自动取消和取消订阅还是我应该手动完成
        猜你喜欢
        • 2019-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-11
        • 1970-01-01
        • 2020-01-25
        • 1970-01-01
        相关资源
        最近更新 更多