【问题标题】:How to make HTTP calls inside a loop and wait for one to finish before making another?如何在循环中进行 HTTP 调用并等待一个完成后再进行另一个?
【发布时间】:2018-12-25 13:55:42
【问题描述】:

我有一组项目,我想在每个元素上进行 HTTP 调用,等待它完成,然后再进行一次调用,一次只能调用一个。

我试过了:

index(item) {
   return this.service.index(item).pipe(
      map(response => {
         // handle success case
      }),
      catchError(error => {
         // handle error case
      })
   )
}

async processArray(array) {
  const promises = array.map(item => this.index(item));
  await Promise.all(promises);
}

proccessArray(array);

还有 NGRX 效果:

@Effect()
effect$ = this.actions$.pipe(
   ofType<action>(actionTypes.action),
   mergeMapTo(this.store.select(getMyArray)),
   flatMap((request: any[]) => {
       return zip(...request.map(item => {  
         return this.service.index(item).pipe(
               map(response => {
                  // handle success case
               }),
               catchError(error => {
                  // handle error case
               })
            )
         }))
      }),
   );

还尝试在 forforEach 循环中执行此操作,但它们会立即触发所有请求。我怎样才能做到这一点?

【问题讨论】:

  • 你可以在这里使用递归函数,它会在得到前一个数组项的响应后调用自己
  • 您要在哪里进行 HTTP 调用?在request?

标签: javascript rxjs ngrx


【解决方案1】:

如果您正在使用 Promise 并希望在进行另一个调用之前等待每个 Promise 解决,那么 (1) 您不应该使用 Promise.all 因为这将等到所有请求都解决并且 (2) 您需要使用一个普通的旧 for 循环,使您能够等待循环内的异步操作。

async processArray(array) {
  for(var i = 0; i < array.length; i++){
    await yourServiceCall();
  }
}

附带说明:由于您使用的是 async-await,因此请不要忘记 convert 您的可观察到的 Promise。

如果您想摆脱 Promise(和 async-await)并改用纯 RxJS,请查看 concatMap

将每个源值投影到一个 Observable 中,该 Observable 合并到输出 Observable 中,以序列化的方式等待每个源值完成,然后再合并下一个。

例如:

import { from } from 'rxjs/observable/from';

ngOnInit() {
  from(myArray)
    .pipe(concatMap(el => yourServiceCall(el)))
    .subscribe(/* your logic */);
}

【讨论】:

  • concatMap 运营商解决了这个问题。如果前一个已完成,它只会订阅下一个 observable。谢谢!
猜你喜欢
  • 2016-09-09
  • 2021-03-28
  • 2014-10-25
  • 1970-01-01
  • 2021-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多