Как обработать отмененный запрос внутри forl oop in Angular.? - PullRequest
0 голосов
/ 05 августа 2020

В моем приложении 5+ страниц. У меня есть следующий метод для компонента заголовка.

Цель состоит в том, что мне нужно показать статус в заголовке, если пользователь нажимает определенную кнопку. Если я сделаю минимальную или медленную навигацию между страницами ниже, код будет работать нормально. Но если я просматриваю страницы очень часто, запрос отменяется, потому что на некоторых других страницах я вызываю другой набор API. l oop не повторяется для следующих элементов. Мне нужно повторить l oop, если один API отменяется. Как я могу исправить эту проблему? Я не уверен, в чем проблема.

1 Ответ

0 голосов
/ 05 августа 2020

Я вижу несколько проблем. Я считаю, что преобразование наблюдаемого в обещание не только излишне, но и контрпродуктивно. Непосредственное использование наблюдаемых позволит вам использовать функции и операторы 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, переданный по конвейеру этому наблюдаемому.

...