【问题标题】:Is it correct to call one observable in another?在另一个中调用一个 observable 是否正确?
【发布时间】:2020-11-17 00:23:33
【问题描述】:

我有三个服务,每个服务都进行简单的 API 调用并将值返回给客户端,每个 API 调用都依赖于从其他服务获取的一些数据。

像我订阅的第一个 Observable 一样,获取用户数据,然后使用从中获取的数据,我可以调用 Observable,它通过传递从第一个 Observable 获得的两个值来获取参数,然后第三个 Observable 需要来自第一个 Observable 的相同数据Observable 和一个参数来自第二个。

所以我的代码如下所示:

 ngOnInit(): void {
    this.profiloService
      .profilo(this.idNegozio)
      .subscribe((profilo: Profilo) => {
        this.profilo = profilo;

        this.menuService
          .menu(profilo.idNegozio, profilo.piva, 'IT')
          .subscribe((menu: Menu[]) => {
            this.menu = menu;

            this.pluService
              .plu(profilo.idNegozio, profilo.piva, 'IT')
              .subscribe((plus: Plu[]) => {
                this.plus = plus;
                this.filterPlu(menu.id);
              });
          });
      });
  }

从另一个 observable 订阅 Observable 是一种好方法吗?如果不是,最佳做法应该是什么?

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    由于所有 http 调用都是连续的,并且您想在第三次调用中使用第一个 http 响应,因此您应该使用 ConcateMap,如下所示,

    ngOnInit(): void {
        this.profiloService.profilo(this.idNegozio)
            .pipe(
                concatMap((profilo: Profilo) => this.menuService.menu(profilo.idNegozio, profilo.piva, 'IT')
                    .pipe(
                        // you should be able to access profilo here
                        concatMap((menu: Menu[]) => this.pluService.plu(profilo.idNegozio, profilo.piva, 'IT')
                            .map((plus: Plu[]) => {
                                this.plus = plus;
                                this.filterPlu(menu.id);
                            })
                        )
                    )
                ).subscribe()
    
    }
      
    

    注意:请忽略任何括号错误

    【讨论】:

    • concatMap 和 switchMap 与 forkJoin 有什么主要区别吗?通过测试@delsashum 解决方案,它运行良好,并且整个数据同时正确加载
    • 我刚刚读到 concatMap 可以在等待完成时按顺序执行操作,如果我需要取消逻辑,我应该使用 switchMap,但在我的情况下,即使 switchMap 也能正常工作,我应该还是切换到 concatMap?
    • 这取决于用例。 switchMap 也可以。但是由于您的呼叫是按顺序进行的,因此最好使用concateMap
    【解决方案2】:

    您几乎不应该在另一个内部进行订阅。做这样的事情:

      ngOnInit(): void {
        this.profiloService
          .profilo(this.idNegozio)
          .switchMap((profilo) =>
            forkJoin([
              of(profilo)
              this.menuService.menu(profilo.idNegozio, profilo.piva, 'IT'),
              this.pluService.plu(profilo.idNegozio, profilo.piva, 'IT')
            ])
          )
          .subscribe(([profilo,menu,plus]) => {
            this.profilo = profilo
            this.plus = plus
            this.filterPlu(menu.id)
            this.menu = menu
          })
      }
    

    【讨论】:

      【解决方案3】:

      不,这是不正确的。您可能会遇到时间问题。

      您可以将 observable 与 switchMap 或 forkeJoin 之类的运算符组合在一起。

      永远不要在其他订阅中进行订阅。 :-)

      别忘了在 ngOnDestroy 中取消订阅。

      在此处查看示例:Is it good way to call subscribe inside subscribe?

      【讨论】:

        猜你喜欢
        • 2018-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-24
        • 1970-01-01
        • 1970-01-01
        • 2019-01-23
        • 1970-01-01
        相关资源
        最近更新 更多