Angular - проверить, все ли подписчики в списке завершены - PullRequest
1 голос
/ 05 апреля 2019

Я использую интервал для отправки переменного объема данных в цикле forEach в бэкэнд. Я хочу сделать следующее: если первый вызов метода post не завершен, но интервал уже требует вызова метода во второй раз, вызов должен быть заблокирован до завершения первого вызова.

Я пытаюсь показать это в коде

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);
   });
 }

Я помещаю всех подписчиков в список, но не знаю, как проверить, все ли запросы завершены

Ответы [ 2 ]

2 голосов
/ 05 апреля 2019

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

1 голос
/ 05 апреля 2019

Я полагаю, что вы хотите вызвать 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)
  }
}

У меня в классе есть флаг, который сообщает, все ли мои запросы выполнены, только если я снова вызываю 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) }))
);
...