【问题标题】:RxJS subscribe inside subscribe with each level returns values and store into respective variablesRxJS subscribe 内部 subscribe 与每个级别返回值并存储到各自的变量中
【发布时间】:2020-02-14 08:21:10
【问题描述】:

我知道已经有关于嵌套订阅的帖子。在这里,我们有 5 个级别的订阅操作,每个变量(operationId、actionlistId、componentId、traceId)。这里Apis正在调用其功能如下。

第 1 步: orderTemplateId 到 apiGetOperationTemplate,将获取值 operationModel 和 operationId。
第 2 步: operationId 到 apiGetActionTemplate,将获取值actionId、actionListId 和 actionModel。
第 3 步: actionId 到 api GetComponentUsageTemplate,将获取值 componentId 和 componentModel。
第 4 步: componentId/ 到 @ 987654324@GetTraceTemplate,将获取值traceId和traceModel。

旧工作代码导致延迟。

  onOrderTemplateClick(selectedData: any): void {
    this.selectedData = selectedData;
    this.descOrderTemplate = selectedData.name;
    this.orderTemplateId = selectedData.id;
    this.orderTemplateFormGroup.controls['orderTemplate'].setValue(this.descOrderTemplate);
    console.log('OperationTemplate');

    this.ordertemplateService.GetOperationTemplate(this.orderTemplateId)
     .subscribe((res: any) => {
        this.operationModel = res;
        if (Object.keys(this.operationModel).length > 0) {
          console.log(this.operationModel);
          console.log('ActionList');
          this.ordertemplateService.GetActionTemplate(this.operationModel[0].id)
             .subscribe((res1: any) => {
              this.actionModel = res1;

              if (Object.keys(this.actionModel).length > 0) {
                this.actionId = res1[0].id;
                this.actionListId = res1[0].parentId;
                console.log(this.actionModel);
                console.log('Action Parameters');

                this.ordertemplateService.GetActionParameterTemplate(this.actionModel[0].parentId)
                 .subscribe((res2: any) => {
                    if (Object.keys(res2).length > 0) {
                      this.actionParamModel = res2;
                      this.actionParameterId = res2[0].id;
                      this.actionParameterId = this.actionParamModel[0].id;
                    } else {
                      this.initializeActionParameterComponentTrace();
                    }
                  });

                console.log('Component Usage');
                this.ordertemplateService.GetComponentUsageTemplate(this.actionModel[0].id)
                 .subscribe((res3: any) => {
                    this.componentModel = res3;
                    this.componentId = res3[0].id;
                    if (Object.keys(this.componentModel).length > 0) {
                      console.log(this.componentModel);
                      console.log('Component Usage');
                      this.ordertemplateService.GetTraceTemplate(this.componentModel[0].parentId)
                        .subscribe((res4: any) => {
                          this.traceModel = res4;
                          if (Object.keys(this.traceModel).length > 0) {
                            this.traceId = res4[0].id;
                            console.log(this.traceModel);
                            console.log('Trace Usage');
                          } else {
                            this.initializeTrace();
                          }

                        });
                    } else {
                      this.traceActions(this.actionModel[0].id);

                    }
                  });


              } else {
                this.initializeComponentTrace();
              }
            }
            );
        } else {
          this.initializeAll();
        }


      });
  }

新的工作代码,我正在尝试使用 switchmap。

 onOrderTemplateClick(selectedData: any): void {
    this.selectedData = selectedData;
    this.descOrderTemplate = selectedData.name;
    this.orderTemplateId = selectedData.id;
    this.orderTemplateFormGroup.controls['orderTemplate'].setValue(this.descOrderTemplate);
    console.log('OperationTemplate');
    this.ordertemplateService.GetOperationTemplate(this.orderTemplateId)
    .pipe(
    switchMap((opData)=> {        
            this.operationModel = opData;
            if (Object.keys(this.operationModel).length > 0) {
              console.log(this.operationModel);
        } else {
                    this.initializeAll();
                }
        }),
    switchMap((actData)=> {
        console.log('ActionList');
            this.actionModel=this.ordertemplateService.GetActionTemplate(this.operationModel[0].id); // actdata[0].id
         if (Object.keys(this.actionModel).length > 0) {
                    this.actionId = this.actionModel[0].id;
                    this.actionListId = this.actionModel[0].parentId;
                    console.log(this.actionModel);
            console.log('Action Parameters');
                    this.actionParamModel = this.ordertemplateService.GetActionParameterTemplate(this.actionModel[0].parentId);
            if (Object.keys(this.actionModel).length > 0) {
            this.actionParameterId = this.actionParamModel[0].id;
            console.log(this.actionParamModel);
            } else {
            this.initializeActionComponentTrace();
            }       
        } else {
                    this.initializeActinonactionParameterComponentTrace();
                }
        }),
    switchMap((cmpData)=> {
        console.log('Component Usage');
        this.componentModel = this.ordertemplateService.GetComponentUsageTemplate(this.actionModel[0].id); // cmpData[0].id
        this.componentId = this.componentModel[0].id;
        if (Object.keys(this.componentModel).length > 0) {
                      console.log(this.componentModel);
                      console.log('Component Usage');
        } else {
                    this.initializeComponentTrace();
                }       
        }),
    switchMap((traceData)=> {
        this.traceModel = this.ordertemplateService.GetTraceTemplate(this.componentModel[0].parentId); // cmpData[0].id
                if (Object.keys(this.traceModel).length > 0) {
                     this.traceId = this.traceModel[0].id;
                     console.log(this.traceModel);
                     console.log('Trace Usage')
         } else {
                     this.initializeTrace();
                 }

    }))
    .subscribe((data)=> {
        if(data!= undefined) {
        console.log(data);
        }
  })
}

以下代码导致延迟 10 秒(最大)。嵌套订阅是否与延迟有关?

【问题讨论】:

  • 如果我遇到这个问题,我会将你的 observables 更改为 Promise 并使用 async/await 模式。
  • 尝试测量每个 http 调用需要多少毫秒
  • @StepUp 将其 150 毫秒提高到 172 毫秒。但是数据量很大,所以延迟太多。
  • 以上新代码有问题吗? @米克斯
  • @wentjun,有什么想法吗?

标签: angular rxjs


【解决方案1】:

一般来说,您的代码没有任何问题(我指的是您更新的代码)。但是,我确实意识到在每个 switchMap() 运算符序列中,您并没有真正发出任何新的可观察值,因此这并不是使用 RxJs 的 switchMap() 运算符的正确方法。

documentation 所述,switchMap 允许您

映射到 observable,完成之前的内部 observable,发出值。

因此,使用tap 运算符可能更合适,因为您只是按顺序执行副作用,并在订阅时返回到链末尾的可观察源。

onOrderTemplateClick(selectedData: any): void {
  this.selectedData = selectedData;
  this.descOrderTemplate = selectedData.name;
  this.orderTemplateId = selectedData.id;
  this.orderTemplateFormGroup.controls['orderTemplate'].setValue(this.descOrderTemplate);
  console.log('OperationTemplate');
  this.ordertemplateService.GetOperationTemplate(this.orderTemplateId)
    .pipe(
      tap((opData) => {
        this.operationModel = opData;
        if (Object.keys(this.operationModel).length > 0) {
          console.log(this.operationModel);
        } else {
          this.initializeAll();
        }
      }),
      tap((actData) => {
        console.log('ActionList');
        this.actionModel = this.ordertemplateService.GetActionTemplate(this.operationModel[0].id); // actdata[0].id
        if (Object.keys(this.actionModel).length > 0) {
          this.actionId = this.actionModel[0].id;
          this.actionListId = this.actionModel[0].parentId;
          console.log(this.actionModel);
          console.log('Action Parameters');
          this.actionParamModel = this.ordertemplateService.GetActionParameterTemplate(this.actionModel[0].parentId);
          if (Object.keys(this.actionModel).length > 0) {
            this.actionParameterId = this.actionParamModel[0].id;
            console.log(this.actionParamModel);
          } else {
            this.initializeActionComponentTrace();
          }
        } else {
          this.initializeActinonactionParameterComponentTrace();
        }
      }),
      tap((cmpData) => {
        console.log('Component Usage');
        this.componentModel = this.ordertemplateService.GetComponentUsageTemplate(this.actionModel[0].id); // cmpData[0].id
        this.componentId = this.componentModel[0].id;
        if (Object.keys(this.componentModel).length > 0) {
          console.log(this.componentModel);
          console.log('Component Usage');
        } else {
          this.initializeComponentTrace();
        }
      }),
      tap((traceData) => {
        this.traceModel = this.ordertemplateService.GetTraceTemplate(this.componentModel[0].parentId); // cmpData[0].id
        if (Object.keys(this.traceModel).length > 0) {
          this.traceId = this.traceModel[0].id;
          console.log(this.traceModel);
          console.log('Trace Usage')
        } else {
          this.initializeTrace();
        }

      }))
    .subscribe((data) => {
      if (data != undefined) {
        console.log(data);
      }
    })
}

关于延迟,这可能是因为它是一个相当长的序列,并且您正在调用相当多的操作,这就是为什么它需要很长时间才能完成运行它的原因。我建议您删除任何不需要按顺序运行的函数调用,并在可观察流之外调用它们。

【讨论】:

    【解决方案2】:

    您的代码看起来正确。所以你需要弄清楚代码的哪一部分得到了这么多时间。我建议你使用performance.now() 方法来测量你的代码:

    console.log(`1. performance.now() ${performance.now()}`);
    this.ordertemplateService.GetOperationTemplate(this.orderTemplateId)
    .pipe(
    switchMap((opData)=> {        
        console.log(`2. performance.now() ${performance.now()}`);
        }),
    switchMap((actData)=> {
        console.log('ActionList');
    
    switchMap((cmpData)=> {
        console.log(`3. performance.now() ${performance.now()}`);
        this.componentModel = this.ordertemplateService.GetComponentUsageTemplate(this.actionModel[0].id); // cmpData[0].id
        this.componentId = this.componentModel[0].id;
        if (Object.keys(this.componentModel).length > 0) {
                      console.log(this.componentModel);
                      console.log('Component Usage');
        } else {
                    this.initializeComponentTrace();
                }       
        console.log(`4. performance.now() ${performance.now()}`);
        }),
    switchMap((traceData)=> {
        console.log(`5. performance.now() ${performance.now()}`);
        this.traceModel = this.ordertemplateService.GetTraceTemplate(this.componentModel[0].parentId); // cmpData[0].id
                if (Object.keys(this.traceModel).length > 0) {
                     this.traceId = this.traceModel[0].id;
                     console.log(this.traceModel);
                     console.log('Trace Usage')
         } else {
                     this.initializeTrace();
                 }
    
        console.log(`6. performance.now() ${performance.now()}`);
    }))
    .subscribe((data)=> {
        if(data!= undefined) {
        console.log(data);
        console.log(`7. performance.now() ${performance.now()}`);
        }
    })
    

    然后你会得到一个信息,一段代码需要这么多时间。

    【讨论】:

      猜你喜欢
      • 2017-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-03
      • 1970-01-01
      • 1970-01-01
      • 2019-06-03
      • 1970-01-01
      相关资源
      最近更新 更多