首页 > 解决方案 > 使用点击运算符调用时,子可观察对象无效

问题描述

我对 RxJS 比较陌生,所以我试图更好地了解 Observables 在使用运算符链接在一起时是如何工作的。我可以通过使用订阅链接它们来使它们正常工作,但这是不好的做法。

下面的代码正在一个 Angular 应用程序中使用,该应用程序涉及向用户显示一个表单,允许他们查看和保存应用程序的设置。该表单首先向 API 发出 GET 请求,以接收以 JSON 格式表示的已保存设置。一旦返回,设置就会显示给用户。然后,用户可以修改设置并在满意时保存它们。

问题是,由于某种原因,最终的 observable,setSettings函数内部的那个似乎不能正常工作。从我的控制台日志中,我可以看到该函数正在被 observable inside 调用buildSettingsForm,但是 tap 运算符中的命令似乎什么也没做。

调用console.log(val)永远不会执行,但我知道调用this.getSettingsFromSerial$肯定会被调用,因为我可以看到日志。因此,似乎在执行对 tap 的调用时发生了一些事情,并且实际上没有执行任何内部命令。这是有道理的,因为this.addRange对 for 循环内部的调用也没有被调用,这意味着我的表单是空的。

initSettings(){
    if(this.savedSettingsState !== undefined)
    {
        if(this.unsavedSettingsExist())
        {
          console.log("Unsaved settings exist");
          this.openUnsavedSettingsModal();
          return;
        }
    }

    this.getOrganisations$().pipe(
        exhaustMap((res: AdminOrganisation[]) => {
          this.organisations = res;
          this.currentOrganisationSerial = this.organisations[0].serialRef;
          this.currentOrganisationName = this.organisations[0].serialName;
          return this.buildSettingsForm(this.currentOrganisationSerial);
        })
    ).subscribe();
}

buildSettingsForm(serial: string) {
    this.ipRangeFormGroup = this.formBuilder.group(
        {
          ipRanges: this.formBuilder.array([])
        }
    );

    this.numArrayElements = this.ipRangeFormArray.length;

    return merge(
        this.ipRangeFormArray.valueChanges.pipe(
            tap(_ => {
              this.numArrayElements = this.ipRangeFormArray.length;
              console.log("numArrayElements: " + this.numArrayElements)
            })
        ),
        this.setSettings(serial)
    );
}

setSettings(serial: string) {
    console.log("setSettings");
    return this.getSettingsFromSerial$(serial).pipe(
        tap(val => {
          console.log("val");
          console.log(val);
          this.savedSettingsState = val;
          this.ipRestrictionEnabled = val.ipRestrictionSettings.ipRestrictionEnabled;
          for (const i of val.ipRestrictionSettings.ipRanges) {
            this.addRange(i.startRange, i.endRange, i.label);
          }
          this.displayForm = true;
        })
    );
  }

标签: angularrxjs

解决方案


我进行了一次闪电战,表明这里的代码没有任何问题:

https://stackblitz.com/edit/angular-v9x1js?file=src/app/app.component.ts

问题出在管道中的其他地方,导致未处理或被吞没的异常,可能发生在getSettingsFromSerial$正在执行的任何操作中。向您的订阅添加错误处理程序并记录它可能有助于弄清楚发生了什么。当有人让拦截器吞下他们忘记的所有 http 错误时,我也看到过类似的神秘问题。


推荐阅读