[英]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.