如何合并这两个可观察变量并删除嵌套的可观察变量?

时间:2019-08-28 11:20:36

标签: angular rxjs

我正在努力了解如何合并两个可观察对象并利用它们的合并产品。我已经看了无数关于mergeMap,switchMap,flatMap,大理石图等的视频,但是我仍然不知道如何合并可观察对象。我觉得使用RxJS时效率不高,甚至不正确。

我有一个可观察的对象,我也想在我的代码中订阅特定表单数组的valueChanges可观察的对象。但是,我需要确保仅在正确构建表单数组之后才进行第二次订阅,否则我将得到null错误。

很显然,这样做是为了在我的第一个订阅的下一个函数中订阅valueChanges,但是这是一种不好的做法,我想避免这样做。但是,我不确定应该以哪种方式构造代码,以便在不使用嵌套订阅的情况下获得所需的行为。

setSettings$(serial: string) {
    return this.getSettingsFromSerial$(serial).pipe(
      tap(val => {
        this.settingsState.savedSettingsState = val;
        this.settingsState.ipRestrictionEnabled = val.ipRestrictionSettings.ipRestrictionEnabled;
        if(val.ipRestrictionSettings.ipRanges.length === 0){
          this.addEmptyRange();
        }
        else
        {
          for (const i of val.ipRestrictionSettings.ipRanges) {
            this.addRange(i.startRange, i.endRange, i.label);
          }
        }
        this.settingsState.displaySettings = true;
        this.settingsState.displayForm = true;
        this.hideRangeErrorsUntilNotPristine(); <-- I need to merge (?) this with my first observable to ensure that it happens after the form is built.
      })
    );
  }

  // TODO :: Cancel this on destroy 
  hideRangeErrorsUntilNotPristine(){
    this.ipRangeFormArray.valueChanges.subscribe( res => {
      let formGroups = this.ipRangeFormArray.controls;

      for(let i = 0; i < formGroups.length; i++){
        if(formGroups[i].pristine === true) {
          this.settingsState.ipRangeValidStates[i].displayError = false;
        }
        else {
          this.settingsState.ipRangeValidStates[i].displayError = true;
        }
      }
    });
  }

1 个答案:

答案 0 :(得分:0)

据我了解,您要做的就是确保在TypeScript代码中实例化FormControl对象后立即调用此方法。我之所以选择mergeMap并没有特别的理由,因为您只需要担心如果外部Observable发出多次,则要使用哪个运算符。

setSettings$(serial: string) {
    return this.getSettingsFromSerial$(serial).pipe(
      tap(val => {
        this.settingsState.savedSettingsState = val;
        this.settingsState.ipRestrictionEnabled = val.ipRestrictionSettings.ipRestrictionEnabled;
        if(val.ipRestrictionSettings.ipRanges.length === 0){
          this.addEmptyRange();
        }
        else
        {
          for (const i of val.ipRestrictionSettings.ipRanges) {
            this.addRange(i.startRange, i.endRange, i.label);
          }
        }
        this.settingsState.displaySettings = true;
        this.settingsState.displayForm = true;
      }),
      // this gets called once everything in the `tap` has finished,
      // because everything is synchronous
      mergeMap(() => this.hideRangeErrorsUntilNotPristine())
    );
  }