繁体   English   中英

如何在 RXJS 订阅中实现 While 循环

[英]How to implement While loop inside RXJS subscription

我有一个 Angular 代码,我在其中尝试订阅我的第一个 api 并在此订阅中实现一个 while 循环。 此外,我需要在 while 循环中订阅另一个 api。 原因 --> 我需要多次订阅内部 api,while 循环应该基于内部 api 返回的标志结束。 我尝试实施以下但它不工作。 需要一些帮助。

CallBanyanToFetchQuotes() {
    const url1 = 'http://ws.integration.banyantechnology.com/services/api/rest/ImportForQuote';

    this.http.post(url1, payload)
      .subscribe(importForQuoteResponse => {
        this.importForQuoteResponse = importForQuoteResponse;
        console.log('LoadID = ' + this.importForQuoteResponse.Load.Loadinfo.LoadID);
        this.loadId = this.importForQuoteResponse.Load.Loadinfo.LoadID;

        while (!this.ratingCompleted) {
          const url2 = 'http://ws.integration.banyantechnology.com/services/api/rest/GetQuotes';

          this.http.post(url2, payload)
            .subscribe(getQuoteResponse => {
              this.getQuoteResponse = getQuoteResponse;
              if (this.getQuoteResponse.RatingCompleted === true) {
                this.ratingCompleted = true;
              }
            });
        }
      });
  }
this.http.post(url1, payload).pipe(
   switchMap(importForQuoteResponse=>{
      this.importForQuoteResponse = importForQuoteResponse;
      this.loadId = this.importForQuoteResponse.Load.Loadinfo.LoadID;
      return timer(0,1000).pipe(
         switchMap(()=>this.http.post(url2, payload)),
         tap(res=>this.getQuoteResponse=res),
         takeWhile(res=>!res.RatingCompleted,true),
         filter(res=>res.RatingCompleted === true)
      )
   })).subscribe(()=>{
     this.ratingCompleted = true;
   })

stackblitz 中的一个“傻瓜例子”

之前的代码可以解释为:我们发表了第一篇文章,但是,我们不想要这个订阅,所以我们将这个订阅更改为一个计时器(switchMap)。 但是我们不想要计时器,否则需要第二篇文章(另一个 switchMap)。 每次执行计时器时,都会在第二个帖子中执行,我们使用 tap 获得响应。 我们在响应为假时进行调用(takeWhile) - 重要的是使 takewhile(...,true),“true”返回最后一个值 - 并过滤响应(过滤器)所以只得到“订阅”当响应为真时。

注意:我使用 timer(0,1000) 每 1000 毫秒拨打一次电话,随时更改间隔

您可以使用expand来模拟 while 循环。 expand将输入立即传递到目的地,映射到 Observable 并接收其输出作为下一个输入。 映射到EMPTY以结束此递归。

// move the urls out of the function if they are static
const url1 = 'http://ws.integration.banyantechnology.com/services/api/rest/ImportForQuote';
const url2 = 'http://ws.integration.banyantechnology.com/services/api/rest/GetQuotes';

callBanyanToFetchQuotes() {
    this.http.post(url1, payload).pipe(
      // process response from url1 http request
      tap(importForQuoteResponse => {
        this.importForQuoteResponse = importForQuoteResponse;
        console.log('LoadID = ' + this.importForQuoteResponse.Load.Loadinfo.LoadID);
        this.loadId = this.importForQuoteResponse.Load.Loadinfo.LoadID;
      }),
      // switch to url2 http request
      switchMap(_ => this.http.post(url2, payload))
      // execute url2 request again if the rating is incomplete or end execution with EMTPY
      expand(quoteResponse => quoteResponse.RatingCompleted ? EMPTY : this.http.post(url2, payload))
      // process responses from url2 requests  
    ).subscribe(quoteResponse => {
      this.getQuoteResponse = quoteResponse;
      if (quoteResponse.RatingCompleted === true) {
        this.ratingCompleted = true;
      }
    });
}

expand方法保证下一个 http 调用将直接进行,并且只有在您收到上一个响应之后。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM