如何防止多个HTTP请求一次触发

时间:2019-05-18 08:14:31

标签: javascript angular typescript rxjs rxjs-pipeable-operators

我有一个对象数组。对于每个对象,我需要触发一个异步请求(http调用)。但我只想同时运行一定数量的请求。另外,如果在所有请求执行完某些代码后都可以有一个同步点,那将是很好的(但不是必需的)。

我尝试了以下建议:

Limit number of requests at a time with RxJS

How to limit the concurrency of flatMap?

Fire async request in parallel but get result in order using rxjs

还有更多...我什至尝试创建自己的运算符。

这些页面上的答案太旧而无法使用我的代码,或者我不知道如何将所有内容放在一起,以便所有类型都很好。

这是我到目前为止所拥有的:

for (const obj of objects) {
  this.myService.updateObject(obj).subscribe(value => {
    this.anotherService.set(obj);
  });
}

编辑1: 好吧,我想我们到了!有了 Julius pschild 的答案(两者似乎均能正常工作),我设法限制了请求的数量。但是现在,它只会发射第一批4,而不会发射其余的。所以现在我有:

const concurrentRequests = 4;
from(objects)
  .pipe(
    mergeMap(obj => this.myService.updateObject(obj), concurrentRequests),
    tap(result => this.anotherService.set(result))
  ).subscribe();

我在subscribe()上做错什么了吗?

顺便说一句:不推荐使用带有mergeMap参数的resultSelector,所以我使用了不带mergeMap的参数。 另外,obj的{​​{1}}在mergeMap中不可见,因此我不得不使用tap的参数

编辑2:

确保观察者完整! (花了我一整天)

3 个答案:

答案 0 :(得分:3)

您可以使用mergeMap的第三个参数来限制并发内部订阅的数量。在所有请求完成后,使用finalize执行一些操作:

const concurrentRequests = 5;
from(objects)
    .pipe(
        mergeMap(obj => this.myService.updateObject(obj), concurrentRequests),
        tap(res => this.anotherService.set(res))),
        finalize(() => console.log('Sequence complete'))
    );

请参见Stackblitz上的示例。

答案 1 :(得分:2)

from(objects).pipe(
  bufferCount(10),
  concatMap(objs => forkJoin(objs.map(obj => 
    this.myService.updateObject(obj).pipe(
      tap(value => this.anotherService.set(obj))
  )))),
  finalize(() => console.log('all requests are done'))
)

代码未经测试,但是您可以理解。让我知道是否需要任何错误或解释

答案 2 :(得分:0)

我曾经遇到过同样的问题。当我尝试从服务器加载多个图像时。我不得不一次又一次发送http请求。我使用期待已久的承诺实现了预期的结果。这是示例代码:

async ngOnInit() {
    for (const number of this.numbers) {
      await new Promise(resolve => {
        this.http.get(`https://jsonplaceholder.typicode.com/todos/${number}`).subscribe(
          data => {
            this.responses.push(data);
            console.log(data);
            resolve();
          }
        );
      });
    }
  }

这里的主要思想是在收到响应后解决承诺。 使用这种技术,您可以提出自定义逻辑,以在所有请求完成后执行一种方法。

这里是stackblitz。打开控制台以查看操作。 :)