【问题标题】:Handling nested subscribes with a dependency处理具有依赖关系的嵌套订阅
【发布时间】:2022-01-26 19:05:09
【问题描述】:

我有一个看起来像这样的模型:

export class Info {
  Id: number;
  Participant: object;
}

我有一个端点,它获取Info 对象的列表,但它不获取Participant 属性。我需要从不同的服务中获取这些对象,但我无法理解如何使用多个 Observables 以及一个依赖于返回的前一个值的对象。

我正在获取Info 的数组,然后通过该数组从其他服务获取Participant 对象。我将组件的视图部分分配到可观察对象之外,因此在显示值之前遇到问题,直到值实际存在。

部分.html

<tr *ngFor="let connection of connections">
    <td> {{connection.Id}} </td>
    <td> {{connection.Participant.Name}} </td>
</tr>

组件.ts

ngOnInit() {
    this.connectionInfoService.GetInfo().subscribe((connections: Info[]) => {
      connections.forEach(x => {
        this.participantService.getParticipantByID(x.Id).subscribe((participant) => {
          x.Participant = participant;
        });
      });

      this.connections = connections;
   });
}

我在控制台中得到Cannot read properties of null (reading 'Name'),因为Name 显然不是null 的属性,直到Participant 实际上有一个值。我怎样才能更好地处理这个问题?我宁愿在我的ngOnInit 服务获取代码中处理它,但我不知道如何处理依赖于另一个类似 Observable 的 Observable。

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    你不应该在另一个subscribe 中包含subscribe。当您需要转换从 Observable 发出的数据时,请使用 RxJs 运算符。

    以下代码未经测试,但希望它足够接近让您走上正轨:

    import { combineLatest } from 'rxjs';
    import { map, switchMap} from 'rxjs/operators';
    
    // ...
    
    
      ngOnInit() {
        this.connectionInfoService.GetInfo().pipe(
          switchMap(connections => {
            // For each connection...
            const connections$ = connections.map(connection => {
              // Create an Observable to fetch the participant.
              const participant$ = this.participantService.getParticipantByID(connection.Id);
              return participant$.pipe(
                // When the participant is recieved, add the participant
                // to the connection and return the connection.
                map(participant => {
                  connection.Participant = participant;
                  return connection;
                })
              );
            });
            // Use the RxJs combineLatest function to return an Observable that
            // emits when all the connections$ Obervables have emitted.
            return combineLatest(connections$);
          })
        ).subscribe(connections => this.connections = connections);
      }
    

    除此之外:我使用了在引用 Observables 的变量中添加尾随 $ 的约定。您可以阅读有关该约定的更多信息here

    此示例中的关键 RxJs 运算符是 switchMap 运算符。使用这个操作符,每次外部 Observable 发出时,switchMap 将有效地订阅内部 Observable。在这种情况下,外部 Observable 为this.connectionInfoService.GetInfo(),内部 Observable 为combineLatest(connections$)

    奖金

    与其在组件类中订阅 Observable,不如考虑使用 Angular 的async pipe

      ngOnInit() {
        this.connections$ = this.connectionInfoService.GetInfo().pipe(
          // same as shown above.
        );
      }
    
    <tr *ngFor="let connection of connections$ | async">
        <td> {{connection.Id}} </td>
        <td> {{connection.Participant.Name}} </td>
    </tr>
    

    【讨论】:

    • 谢谢 - 这帮助我理解了它。
    猜你喜欢
    • 2020-10-17
    • 1970-01-01
    • 2019-10-25
    • 2021-11-19
    • 1970-01-01
    • 2010-10-07
    • 2017-03-15
    • 2015-05-11
    • 2018-11-28
    相关资源
    最近更新 更多