#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)
);
}
Ответ №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
версии. Я считаю, что конвейерные операторы были введены из rxjs5.1
, (это должно быть хорошо для вас). В моем приведенном примере импорт изrxjs
может отличаться от того, что было бы доступно для вас.3. @WeSt Проверьте мою правку на предмет обработки ошибок в отдельных вызовах API