【问题标题】:RXJS: How do I utilize the emitted observable at the end of the processing stream?RXJS:如何在处理流结束时利用发出的 observable?
【发布时间】:2021-12-25 23:31:41
【问题描述】:

假设我有一个函数generateIdUpdate,它使用一个可观察的 id 来加载属于该 id 的人的地址。我想在成功完成地址加载后设置一个实例变量来保存选定的 id。最好的方法是什么?

另外,这是否反映了糟糕的设计(即,有一个函数加载地址在最后更新有状态字段)?

export class TapTest {
  private selectedId: number;
  private id$: Observable<number> = ...;
  
  generateIdUpdate$(): Observable<PersonAddress> {
    return id$.pipe(
      // switchMap in case a new Id is selected while loading
      switchMap(id => loadPerson(id)),
      // Get the observable of addresses
      mergeMap((person: Person) => loadAddresses(person)), 
      tap(
        // since this completed successfully, set the selectedId field to the id
      )
    );
  }

  loadPerson(id: number) : Person { ... }
  loadAddresses(person: Person) : Observable<PersonAddress> { ... }
}

给定以下函数,它尝试获取发出的 id、加载人员、加载地址并返回它们,而且在将地址加载到实例变量时更新人员的有状态 id,正确的方法是什么通过处理流“携带” id?

【问题讨论】:

    标签: rxjs


    【解决方案1】:

    如果我正确理解您想要做什么,我会以与您所描述的非常相似的方式解决问题,但有一些小的变化(请参阅我的 cmets)

    export class TapTest {
      private selectedId: number;
      private id$ = ...;
      
      generateIdUpdate$(): Observable<PersonAddress> {
        return id$.pipe(
          // switchMap in case a new Id is selected while loading
          // loadPerson is a function that returns an Observable and not a function
         // that returns a Person as in your original example
         // otherwise switchMap will not work and actually will not even compile
          switchMap(id => loadPerson(id)),
          // Get the observable of addresses
          // Rather than mergemap I would use concatMap, which basically means
          // "wait until I complete before processing the next notification of my
          // upstream Observable" 
          concatMap((person: Person) => loadAddresses(person)), 
          tap(
            // since this completed successfully, set the selectedId field to the id
            // the tap operator expects a an Observer as input parameter
            // an Observer is an object with 3 properties, next, error and complete
            // each of these property is optional
            // in this case we will define the next property as a function that expexts
            // the notification as input - in pour case we will use the input to set
            // the instance variable selectedId
            {
               next: (id) => this.selectedId = id
            }
          )
        );
      }
    
      // loadPerson must return an Observable<Person> for the above code to work
      loadPerson(id: number) : Person { ... }
    
      loadAddresses(person: Person) : Observable<PersonAddress> { ... }
    }
    

    无论loadAddress是否成功完成,如果要存储selectedId,可以将tap运算符移到pipe的开头。

    【讨论】:

    • 这对我不起作用:next 函数将 id 转换为 PersonAddress 类型。所以...看来下一个参数需要一个以PersonAddress 作为初始参数的函数,而不是数字。 id$ observable 是一个数字,顺便说一句。我会在代码中说明这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-05
    • 2017-08-02
    • 1970-01-01
    • 1970-01-01
    • 2019-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多