将 switchMap 串在一起

分享于2023年03月01日 angular rxjs 问答
【问题标题】:Stringing switchMap(s) together将 switchMap(s) 串在一起
【发布时间】:2023-02-22 07:11:48
【问题描述】:

我正在构建一个编辑器,允许用户从一组帐户中选择一个帐户(也称为会计科目表 (COA))

作者可以定义需要选择的类型/子类型,编辑器应该只提供满足这种偏好的选择。

有4个步骤:

  1. 获取类型列表和子类型列表,将它们与现实生活中的 T/ST 集合进行比较并返回匹配项(并非每个类型和每个子类型都构成有效组合 - 同步)
  2. 从数据库中获取完整的 COA(异步)
  3. 根据允许的 T/ST 组合(同步)对 COA 进行切片
  4. 用结果数据填充配置对象并将其作为可观察对象返回

    我觉得/相信我在这里拥有的是一种反应性解决方案。

    我看过/读过很多关于在这种情况下使用 switchmap 的文章。

    这个视频对我很有帮助。 https://www.youtube.com/watch?v=Byttv3YpjQk&t=1148s

    我认为 switchmap 是在 combineLatest 上指示的,因为这些步骤取决于先前步骤的数据。

    我面临的挑战是我将这些编码为单独的语句。

    如果我尝试在最终可观察对象中使用第一次调用(名为 a_tst )的数据,我不能。

    这对我来说不是一个阻碍问题,因为我没有 需要 在这种特殊情况下可以追溯到那么远。下次可能有需要...

    我还在配置数据结构中的每一步捕获数据,这似乎是一种常见的做法……所以也许这就是答案?

    我的问题 - 有没有办法将 switchMaps 串在一起,以便尾随的 switchMaps 可以通过链一直返回并访问早期调用发出的值?

    还在学习rxjs。任何 cmets 或建议将不胜感激......

    public hydrate_COA_Editor_Config(config_: COA_Editor_Config, title_: string) : Observable {
      const debug: boolean = false;
          
      if (debug) console.log('svc 0.1', title_, config_);
    
      // get the allowed Type/Subtype combinatinos from the config data structure passed in by caller
      const allowedTST$ = this.get_coa_Allowed_TST_List(config_.AccountTypes, config_.AccountSubTypes);
                 
             
      const Accounts$ = allowedTST$.pipe(
        tap(a_tst => {
          if(debug) console.log('1.0', title_, 'allowed tst', a_tst);
    
          config_.allowed_TST = a_tst;
        }),
        // ask the service for ALL accounts available for this project
        switchMap(a_tst => this.getCOAByProjectId(config_.projectId))
      );   
        
      const allowedAccounts$ = Accounts$.pipe(
        tap(acctHeader => {
          if(debug) console.log('svc 2.0', title_, 'all accts', acctHeader.Accounts);
    
            // myAccounts = acctHeader.Accounts;
        }),
        // find the set of Accounts which match the caller's indicated types/subtypes
        switchMap(acctHeader => this.get_coa_Allowed_Account_List(acctHeader.Accounts, config_.allowed_TST.items))
      );
        
      // return the config as an observable. It has now been populated w/ all the data needed to do its job.
      const config$: Observable = allowedAccounts$.pipe(
        tap(a_accts => {
          // if(debug) console.log('3.0', title_, a_accts);
    
          config_.allowedAccounts = a_accts;
          config_.hydrated = true;
          // at this point, we have turned the users wishes (allowed types, subtypes) into a list of accounts that match those wishes
        }),
        switchMap(accts => of(config_))
      );
                
      return config$;
    }
    


【解决方案1】:
obs1$.pipe(
  switchMap(result1 => obs2$),
  switchMap(result2 => obs3$), // result1 not available
  switchMap(result3 => obs4$), // result1 and result2 not available
)

如果您将 switchMap 嵌套在下一个可观察管道上

obs1$.pipe(
  switchMap(result1 => obs2$.pipe(
    switchMap(result2 => obs3$.pipe( // result1 still available
      switchMap(result3 => obs4$)  // result1 and result2 still available
    )
  )
)

【讨论】:

  • 看起来你在 obs$ .pipe( 之间放错了括号
  • 谢谢,修好了。