【问题标题】:Wait for SUBSCRIBE block to finish before completing loop在完成循环之前等待 SUBSCRIBE 块完成
【发布时间】:2020-07-23 09:06:27
【问题描述】:

我正在使用循环重复调用 API 并将相应的响应打印到对象中,但在我的第二次订阅完成之前,循环继续前进并执行下一行代码。如何在循环继续之前适当地等待订阅结束?

我希望在第二个循环开始之前完全填充数组 Phone。

getData() {
this.finaldata=[];
this.phone=[];
this.api.getSingleValue('/API/shift/app_name/' + this.application_name).subscribe((Response: any) => {  
  if (Array.isArray(Response) && Response.length > 0) {
     for(let i=0; i<Response.length; i++){
        this.api.getSingleValue('/API/person/' + Response[i].qlid).subscribe((res: any) => {
        this.phone.push(res.contactNumber)   
      });  
    }
    console.log(this.phone)
    for(let i=0; i<Response.length; i++){
      this.object={
        "qlid": Response[i].qlid,
        "entry_Type": Response[i].entry_Type,
        "app_Name": Response[i].app_Name,
        "shift_Start_Time": Response[i].shift_Start_Time,
        "shift_End_Time":Response[i].shift_End_Time,
        "startDate": Response[i].startDate,
        "endDate": Response[i].endDate,
        "reason": Response[i].reason,
        "phone_no": this.phone[i]
      }
      this.finaldata.push(this.object);
    }
    console.log(this.finaldata)
    this.rowData = this.finaldata;
   
  }
  
  else{
    this.rowData=[];
    alert('No Data To Display')
    
  }
  
});

    
  }


}

【问题讨论】:

标签: angular typescript


【解决方案1】:

尽量避免循环订阅和嵌套订阅。您可以使用 RxJS 运算符来简化您的程序。

订阅工作流程:

  1. 调用this.api.getSingleValue('/API/shift/app_name/' + this.application_name) 并使用switchMap 将其切换为另一个可观察对象。

  2. switchMap中,使用iif检查响应是否有效。

  3. 如果是,则将数组中的值映射到 this.api.getSingleValue('/API/person/' + &lt;response&gt;.qlid)) 数组并使用 forkJoin 组合 observables。使用map 运算符进一步处理响应,将值推送到this.finaldata 变量并返回。

  4. 如果不是,则使用throwError 运算符抛出错误。

  5. 在订阅中,分别使用nexterror回调处理响应(this.finaldata变量)和错误。

试试下面的

getData() {
  this.finaldata = [];
  this.phone = [];
  this.api.getSingleValue('/API/shift/app_name/' + this.application_name).pipe(
    switchMap((Response: any) =>
      iif(
        () => Array.isArray(Response) && Response.length > 0,
        forkJoin(Response.map(res => this.api.getSingleValue('/API/person/' + res.qlid))).pipe(
          map(phone => {
            this.phone = phone.map(number => number.contactNumber);
            console.log(this.phone);
            for(let i=0; i < Response.length; i++){
              this.object = {
                "qlid": Response[i].qlid,
                "entry_Type": Response[i].entry_Type,
                "app_Name": Response[i].app_Name,
                "shift_Start_Time": Response[i].shift_Start_Time,
                "shift_End_Time":Response[i].shift_End_Time,
                "startDate": Response[i].startDate,
                "endDate": Response[i].endDate,
                "reason": Response[i].reason,
                "phone_no": this.phone[i]
              }
              this.finaldata.push(this.object);
            }
            console.log(this.finaldata);
            return this.finaldata;
          })
        ),
        throwError('Response was empty');
      )
    )
  ).subscribe(
    (finaldata: any) => {
      this.rowData = finaldata;
    },
    error => {
      this.rowData = [];
      alert('No Data To Display')
    }
  );
}

更新:删除除rowData之外的成员变量

如果您仅使用this.finaldatathis.phone 来保存此函数中的信息,则可以将它们全部替换为局部变量。您也可以使用数组forEach 函数而不是手动循环数组。

getData() {
  this.api.getSingleValue('/API/shift/app_name/' + this.application_name).pipe(
    switchMap((Response: any) =>
      iif(
        () => Array.isArray(Response) && Response.length > 0,
        forkJoin(Response.map(res => this.api.getSingleValue('/API/person/' + res.qlid))).pipe(
          map(phones => {
            const contactNumbers = phones.map(phone => phone.contactNumber);
            let output = [];

            Response.forEach((res, index) => {
              output.push({
                "qlid": res.qlid,
                "entry_Type": res.entry_Type,
                "app_Name": res.app_Name,
                "shift_Start_Time": res.shift_Start_Time,
                "shift_End_Time":res.shift_End_Time,
                "startDate": res.startDate,
                "endDate": res.endDate,
                "reason": res.reason,
                "phone_no": contactNumbers[index]
              })
            });

            return output;
          })
        ),
        throwError('No Data To Display');
      )
    )
  ).subscribe(
    (finaldata: any) => {
      this.rowData = finaldata;
    },
    error => {
      this.rowData = [];
      alert(error)
    }
  );
}

【讨论】:

  • 这个 sn-p 工作但并不完美,就像第一次 API 调用的详细信息,如条目类型等(QLID 除外)没有填充,也在电话号码内。整个响应是 biend 发送的,而不仅仅是联系号码。来自第二个 API 调用。
  • @IshankJain:是的,我忽略了一个关键部分。在前面的代码中,来自forkJoin 的通知将被错误地发送到订阅。我编辑了代码以使用map 运算符进行所有处理。然后可以在订阅回调中将其分配给rowData。我还使用数组map 函数仅分配phone 数组中的contactNumber,而不是整个数组。请查看更新后的答案是否适合您。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-26
  • 2018-02-08
  • 1970-01-01
  • 1970-01-01
  • 2012-09-30
  • 2020-01-04
  • 1970-01-01
相关资源
最近更新 更多