Angular - 检查列表中的所有订阅者是否完成

Angular - Check if all Subscriber in a list are finished

我使用间隔 post 将 forEach 循环中的可变数据量发送到后端。我想做的是:如果post方法的第一次调用没有结束,但是interval已经想第二次调用该方法,那么应该阻塞调用,直到第一次调用结束。

我试着在代码中展示这个

setInterval(() => {
  console.log('pendingServiceDataRequests', this.pendingServiceDataRequests);
  if(/* if pendingServiceDataRequests is empty or all subscriber are finished */){
   this.sendData();
  }
}, 5000);


sendData(){
  serviceList = [/* some data */]
  serviceList.forEach((service, index, array) => {
    const currentSub = this.api.post(url, service).subscribe((res: any) => {
            /* delete successful send data */
    }
    this.pendingDataRequests.push(currentSub);
   });
 }

我将所有订阅者都放在一个列表中,但我不知道如何检查是否所有请求都已完成

ConactMap 将是这种情况下的正确选择。试试这个:

sendData() {
    serviceList = [/* some data */]
    return from(serviceList).pipe(
        concatMap(id => <Observable<Item>> this.api.post(url, service)
    );
}

https://blog.angularindepth.com/practical-rxjs-in-the-wild-requests-with-concatmap-vs-mergemap-vs-forkjoin-11e5b2efe293

我相信您想在完成所有请求后调用 sendData() 并每隔一段时间调用一次。尝试做类似的事情:

ngOnInit() {
  this.timer = setInterval(() => {
    if (!this.activeObservable) {
      this.sendData().subscribe((data) => {
        console.log(data);
      })
    }
  }, 5000)
}

sendData() {
  this.activeObservable = true;
  // probably you are calling some service to get a fresh lisyt of data and do post requests over them
  let serviceList = [1,2,3,4,5]; // consider this is your sendData
  // create observables in a loop, don't subscribe them:
  // for you, something like:
  //let allPostData = serviceList.map(service => this.api.post(url, service));
  let dummyPostData = serviceList.map(service => of(service));
  return forkJoin(...dummyPostData).pipe(tap(_ => {this.activeObservable = false;}));
}

ngOnDestroy() {
  if (this.timer) {
    clearTimeout(this.timer)
  }
}

我在 class 中有一个标志,它告诉我是否所有请求都已完成,只有它们我再次调用 sendData(),看看我如何设置 activeObservable

https://stackblitz.com/edit/angular-ggwnxv

要处理单个 API 调用中的错误,请执行以下操作:

let allPostData = serviceList.map(service => this.api.post(url, service).pipe(
    catchError((e) => { return throwError(e); // handle your error here, can also return of(e) }))
);