如何避免Angular/RxJS中的嵌套订阅-一个接一个的调用(顺序/非并行)和循环的http api调用



我有一个来自angular的situation to make a nested rest api call。我必须拨打下面给出的上一个电话的one call after another call based on the result

OuterLoop: while (1) {
getHttpResponse1().subscribe((value1) => {
if (value1 == 'A') {
InnerLoop: while (1) {
getHttpResponse2().subscribe((value2) => {
if (value2 == 'B') {
break OuterLoop;
} else {
continue InnerLoop
}
})
}
}else {
continue OuterLoop;
}
})
}

我需要在first loop infinite timeutil中进行http调用,我得到expected result,一旦我收到预期结果,我就需要使another http call (second loop) infinite timeutil得到expected result,之后我必须中断所有循环。

我有tried below code,它可以用于一个http调用,但我想根据第一个调用的结果进行另一个调用,我最终再次陷入嵌套订阅。

const sub1 = interval(1000).subscribe(() => {       // http call every second 
this.apiservice.getHttpResponse1()
.pipe(takeWhile(val => val))                    // receive true / false
.subscribe(val => {                             // if true or ignored
console.log("loopOne" + val)
sub1.unsubscribe()
const sub2 = interval(1000).subscribe(() => { // http call every second 
this.apiservice.getHttpResponse2()
.pipe(takeWhile(val2 => val2))            // receive true / false
.subscribe(val2 => {                      // if true or ignored
console.log("loopTwo" + val2)
sub2.unsubscribe()
})
})
})
})
}

this the only approach吗?我觉得有点乱。等等,我觉得switchMap, mergeMap are inappropriate为我的问题。

我想avoid nested subscription / http calls

你有any better solution吗?

实际上,您走在了正确的轨道上。要使嵌套订阅变平,需要使用mergeMapswitchMapconcatMap运算符。

这些运算符允许您管理订阅流。

这些运营商之间的区别的简短解释:

mergeMap–当您希望展平内部可观察对象,但希望手动控制内部订阅的数量时,最好使用此运算符。

switchMap–当操作员获得一个值时,它切换到另一个可观察到的值并取消前一个值。

concatMap–在每次发射时,取消先前的内部可观测值(您提供的函数的结果(,并订阅新的可观测值。

您当前的实现方式如下所示:

interval(1000)
.pipe(
// when we get value from the interval => make a request
mergeMap(() => this.apiservice.getHttpResponse1()),
takeWhile(val1 => val1),
// when we get the desired value, switch to the next interval
switchMap(() => interval(1000)),
// when we get value from the interval => make a request
mergeMap(() => this.apiservice.getHttpResponse2()),
takeWhile(val2 => val2),
).subscribe();

p.S.在本例中,switchMap可以替换为任何其他映射运算符,因为之前的订阅是通过takeWhile取消的。

p.p.S.您在这里所做的事情叫做长轮询。你可以在谷歌上找到许多有趣的方法来更好地组织这些循环请求。

最新更新