简体   繁体   English

How to avoid nested subscriptions in Angular / RxJS - One call after another call (sequentially / not parallel) And looping http api calls

[英]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.要展平嵌套订阅,您需要使用mergeMapswitchMapconcatMap运算符。

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.

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