Я вижу несколько проблем. Я считаю, что преобразование наблюдаемого в обещание не только излишне, но и контрпродуктивно. Непосредственное использование наблюдаемых позволит вам использовать функции и операторы Rx JS. Мы можем использовать функцию forkJoin
для выполнения нескольких одновременных запросов и оператор catchError
для смягчения последствий потенциальных ошибок.
Попробуйте следующее
import { forkJoin } from 'rxjs';
import { catchError } from 'rxjs/operators';
geneStatus() {
forkJoin(Object.keys(this.gene).map(gene => this.fetchEachStatus(gene['name']))).subscribe(
res => {
// res[0] - `{ success: true | false, geneId: geneId }` from `this.apiDataService.get(this.geneUrl + '/' + this.gene[0]['name'])`
// res[1] - `{ success: true | false, geneId: geneId }` from `this.apiDataService.get(this.geneUrl + '/' + this.gene[1]['name'])`
...
const passedGeneIds = res.filter(item => item.success).map(item => item.geneId);
// passedGeneIds = [`geneId`, `geneId`, ...] - list of passed gene IDs
const failedGeneIds = res.filter(item => !item.success).map(item => item.geneId);
// failedGeneIds = [`geneId`, `geneId`, ...] - list of failed gene IDs
// some other logic
},
error => {
// essentially will never be hit since all the errors return a response instead
}
);
}
fetchEachStatus(geneId): Observable<any> {
return this.apiDataService.get(this.geneUrl + '/' + geneId).pipe(
map(_ => ({ sucess: true, geneId: geneId })), // <-- map to return the `geneId`
catchError(error => of({ sucess: false, geneId: geneId })) // <-- retun an observble from `catchError`
);
}
Теперь вам нужно помнить, что каждый раз, когда нажимается кнопка, запускаются несколько одновременных запросов. Одним из решений этой проблемы является отмена всех текущих запросов перед запуском нового набора запросов. Для этого вы можете привязать кнопки к генерации центрального наблюдаемого и запускать запросы, используя оператор switchMap
, переданный по конвейеру этому наблюдаемому.