[英]How to avoid nested subscriptions in Angular / RxJS - One call after another call (sequentially / not parallel) And looping http api calls
I have a situation to make a nested rest api call
from angular.我有一种
situation to make a nested rest api call
api。 I have to make one call after another call based on the result
of previous call as given below我必须
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;
}
})
}
I need make http call in first loop infinite time
util
i get expected result
, once i received the expected result then I need to make another http call (second loop) infinite time
util
i get expected result
after that i have to break all loops.我需要在
first loop infinite time
调用util
使用我得到expected result
,一旦我收到预期的结果,然后我需要进行another http call (second loop) infinite time
util
得到expected result
之后我必须打破所有循环。
I have tried below code
which ok for one http call but I want to make another one based on the result of first one, I end up in nested subscription again.我已经
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()
})
})
})
})
}
Is this the only approach
?这
this the only approach
吗? I felt it's kind of mess.我觉得有点乱。 I am new to
switchMap, mergeMap
and so on and I felt it's not appropriate
for my problem.我是
switchMap, mergeMap
等的新手, I felt it's not appropriate
我的问题。
I want to avoid nested subscription / http calls
?我想
avoid nested subscription / http calls
?
Do you have any better solution
?你有
any better solution
吗?
Actually, you're on the right track.事实上,你在正确的轨道上。 To flatten the nested subscriptions you need to use
mergeMap
, switchMap
, or concatMap
operator.要展平嵌套订阅,您需要使用
mergeMap
、 switchMap
或concatMap
运算符。
These operators allow you to manage your subscriptions flow.这些运算符允许您管理您的订阅流程。
A short explanation of the difference between these operators:这些运算符之间的区别的简短说明:
mergeMap
– this operator is best used when you wish to flatten an inner observable but want to manually control the number of inner subscriptions. mergeMap
- 当您希望展平内部 observable 但想要手动控制内部订阅的数量时,最好使用此运算符。
switchMap
– when the operator gets a value, it switches to another observable and cancels the previous one. switchMap
– 当操作符得到一个值时,它会切换到另一个 observable 并取消前一个。
concatMap
– on each emission the previous inner observable (the result of the function you supplied) is canceled and the new observable is subscribed. concatMap
– 在每次发射时,前一个内部 observable(您提供的 function 的结果)被取消并订阅新的 observable。
Your current implementation will look like that:您当前的实现将如下所示:
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();
PS In this example, switchMap
can be replaced with any other mapping operator, since the previous subscription is cancelled via takeWhile
. PS在这个例子中,
switchMap
可以替换为任何其他映射操作符,因为之前的订阅是通过takeWhile
取消的。
PPS The thing you do here is called long polling . PPS您在这里所做的事情称为长轮询。 You can find many interesting approaches on google on how to better organise these looped requests.
关于如何更好地组织这些循环请求,您可以在 google 上找到许多有趣的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.