循环内的异步请求

问题描述 投票:0回答:1

我有一个功能可以根据订单/请求的数据生成报告。里面的函数有一个循环来查看要产生的展示总数,然后执行一系列操作。

问题是我无法让它线性完成,即先完成一个函数,然后再前进到下一行。

主要功能是:

async request(){
    for (let index = 1; index <= this.numLabels; index++) { 
      let time: number = 0;

      this.p_orderRequest.RequestId=this.generateRandomId().toString().substring(0,9);
      
      this.porderService.InsertRequest(this.p_orderRequest).subscribe(async data => {
        //Start interval with promise to ensure not continue in loop for??
          const responseRequest = await new Promise<void>((resolve, reject)=>{
            this.timerCheck = setInterval(() => {
            time = time +this.INTERVAL_DURATION_MS;
            
            if(data.type === 'success' || data.type ==='error'){              
                if(this.GetProtocol()){
                  console.log("Protocol correct")
                  if(this.CheckPrintEnd()){
                    if(this.blnFinished){
                      if(this.p_orderRequest.result=="OK"){
                                            this.porderService.SaveOrderRegisterControl(this.p_orderRequest).subscribe();
                        this.porderService.SaveSystemAudit(this.p_orderRequest).subscribe();
                      }             
                    this.porderService.DeleteRequest(this.p_orderRequest).subscribe();
                    }
                  }
                }
              
              time = 0;
              console.log("Cycle cycle completed.")
              clearInterval(this.timerCheck)
              resolve();
            }else if(time>this.DEFAULT_TIME_OUT){
              this.p_orderRequest.result="NG:TIMEOUT=" + time
              this.UpdateRequest(this.p_orderRequest, "TIME_OUT");
              clearInterval(this.timerCheck);
              resolve();
              }else{
              console.log("Waiting for the server...")
              }
            },1000);  
          })
         this.numLabelsPrinted++
        });
     }
  }

如果我收到服务器的响应,我会启动一系列函数,直到循环结束并且间隔结束,这样我就可以继续进行下一个打印(如果有)。如果我在规定的时间内没有得到响应,我就配置了超时,尽管这不是让我失败的部分。

大多数情况下,我在 if(GetProtocol()) 和 if(CheckPrintEnd()) 中遇到问题,因为它首先在 GetProtocol() 完成之前执行 console.log("Order Cyclecompleted.") ,因此我不能根据需要关闭打印。

这些功能是:

 GetProtocol(): any{
     this.porderService.GetProtocol(this.p_orderRequest.RequestId).subscribe(data => {
      if (data.type === 'success') {
        return true;
      } else {
        return false;
      }
    });
  }



  CheckPrintEnd():any{
    this.porderService.CheckPrintEnd(this.p_orderRequest).subscribe( data => {
     if (data.type === 'success') {
        this.p_clsRequest = JSON.parse(data.data.toString()) as POrderRequest;
        this.blnFinished = !!(this.p_orderRequest.porderValue);
        return true;
     } else {
       return false;
     }
   });
 }

我尝试了不同的事情,比如用 Promise 来做,在 GetProtocol 和 CheckPrintEnd 中返回 true/false,异步/等待......但没有什么效果。

所以,我希望代码同步运行,先完成一个函数,然后再继续下一个,因为下一个函数需要前一个函数的值。

javascript angular typescript async-await promise
1个回答
0
投票

下面是我尝试摆脱承诺和可观察量的混合,我仅使用 rxjs 来创建一个值流,该值流向下到单个订阅,请仔细阅读所有操作员的文档以更好地理解实现,但是我添加了注释,以便您更好地理解我的实现!

  request() {
    const apiArray$ = of([]);
    for (let index = 1; index <= this.numLabels; index++) {
      this.p_orderRequest.RequestId = this.generateRandomId()
        .toString()
        .substring(0, 9);
        // the below sequence gets executed for each element added by the for loop
      const apiSequence = forkJoin([
      this.porderService
      .InsertRequest(this.p_orderRequest),
      // subscribe cannot be used inside a function, which outputs to the if condition it will always be false, to solve this, we can use a fork join, to preevaluate the conditions simulatenously
      this.porderService.GetProtocol(this.p_orderRequest.RequestId).pipe(
        // great operator to transform the inner values of a stream!
        map(data => {
        if (data.type === 'success') {
          return true;
        } else {
          return false;
        }
      })),
      // subscribe cannot be used inside a function, which outputs to the if condition it will always be false, to solve this, we can use a fork join, to preevaluate the conditions simulatenously
      this.porderService.CheckPrintEnd(this.p_orderRequest).pipe(
        // great operator to transform the inner values of a stream!
        map(data => {
        if (data.type === 'success') {
           this.p_clsRequest = JSON.parse(data.data.toString()) as POrderRequest;
           this.blnFinished = !!(this.p_orderRequest.porderValue);
           return true;
        } else {
          return false;
        }
      }))
    ]).pipe(
        // great for sequential executions, first one runs, then the below code
        switchMap(([data, protocolBool, checkPrintEndBool]) => {
          if (data.type === 'success' || data.type === 'error') {
            if (protocolBool) {
              console.log('Protocol correct');
              if (checkPrintEndBool) {
                if (this.blnFinished) {
                  if (this.p_orderRequest.result == 'OK') {
                    return this.porderService
                      .SaveOrderRegisterControl(this.p_orderRequest)
                      .pipe(
                        // great for sequential executions, first one runs, then the below code
                        switchMap(() => {
                          // assuming you want this to be executed after the top one!
                          return this.porderService
                            .SaveSystemAudit(this.p_orderRequest);
                        })
                      );
                  }
                  return this.porderService
                    .DeleteRequest(this.p_orderRequest)
                }
              }
              // for all the other cases, we return the default value
              // no case was executed!
              return of(false);
            }
        })
      )
      // adding the APIS to the for loop
      apiArray$.push(apiSequence);
    }
    // runs this observable array in parallel, returns all the values at once!
    forkJoin(apiArray$).subscribe((output: any) => {
      this.numLabelsPrinted = output.length;
      console.log(output);
    });
  }
© www.soinside.com 2019 - 2024. All rights reserved.