Angular — проверка, завершены ли все подписчики в списке

#angular #post #foreach #angular5 #subscriber

#angular #Публикация #foreach #angular5 #подписчик

Вопрос:

Я использую интервал для отправки переменного объема данных в цикле 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);
   });
 }
  

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

Ответ №1:

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

Ответ №2:

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

Комментарии:

1. Возможно ли это с Angular 5? Но что мне все еще нужно, так это выполнить некоторые операции, если один из запросов выполнен или сбой

2. @WeSt Да, это было бы возможно с angular 5, изменения могут произойти в зависимости от вашей rxjs версии. Я считаю, что конвейерные операторы были введены из rxjs 5.1 , (это должно быть хорошо для вас). В моем приведенном примере импорт из rxjs может отличаться от того, что было бы доступно для вас.

3. @WeSt Проверьте мою правку на предмет обработки ошибок в отдельных вызовах API