Цепочка динамического числа HTTP-вызовов в Angular 7 - PullRequest
0 голосов
/ 26 марта 2019

Я занимаюсь разработкой приложения и столкнулся с некоторыми трудностями в следующей ситуации.

У меня есть URL, который в конце принимает pageSize и текущую страницу, и я пытаюсь использовать этот URL, получить в списке все элементы из таблицы базы данных, не зная, сколько страниц я на самом деле иметь (может быть одна страница данных или 1 миллион страниц).

Например, после того, как я сделаю запрос, скажем, с размером страницы 50 и страницей 1, я хочу получить страницу 2, а если страница 2 содержит 50 элементов, получить страницу 3, если она имеет значение меньше 50 элементы, чтобы остановиться и вернуть в конце концов все данные, которые я получил до сих пор, и ничего не будет возвращено, пока я не сделаю последний запрос.

Я пытался сделать следующее:

 return this.http.get(url + currentPage, { headers }).pipe(
 mergeMap((response: any) => {
    managedObject = managedObject.concat(response.managedObjects);
    if (response.managedObjects.length === pageSizeNo) {
      currentPage++;
      this.http.get(url + currentPage, { headers });
    } else {
      return managedObject;
    }
  })
);

Сначала я даю URL с определенным в нем pageSizeNo = 50 и currentPage = 1, затем после получения ответа я хочу пойти дальше и сделать еще один вызов или вернуть все, что я получил до сих пор. Проблема в том, что все останавливается на странице 2, и дальнейший вызов не происходит.

Вот как я подписываюсь на то, что возвращает функция:

this.service.fetchData()
  .subscribe((response: any) => {
    this.qualityData = response
});

Как я могу это исправить?

Ответы [ 2 ]

1 голос
/ 26 марта 2019
function getPage(pageNo: number): Observable<{ managedObjects: any[] }> {
  return this.http.get(`url?page=${pageNo}`, { headers });
}

of([0, false, []] as [number, boolean, any[]]).pipe(
  expand(([pageNo, isFinal, allResults]) => getPage(pageNo).pipe(
    map(newResults => [
      pageNo + 1,
      newResults.managedObjects.length < 50,
      [...allResults, ...newResults.managedObjects]
    ] as [number, boolean, any[]])
  )),
  takeWhile(([pageNo, isFinal, allResults]) => !isFinal, true),
  last(),
  map(([pageNo, isFinal, allResults]) => allResults)
).subscribe(finalResults => {
  // ...
});

См .: https://stackblitz.com/edit/rxjs-tyuefr?file=index.ts для рабочего примера

1 голос
/ 26 марта 2019

Используйте оператор expand для рекурсивного вызова http-get.Например:

return this.http.get(url + currentPage, { headers }).pipe(
 expand((response: any) => {
    managedObject = managedObject.concat(response.managedObjects);
    if (managedObject.length === pageSizeNo) {
      currentPage++;
      return this.http.get(url + currentPage, { headers });
    } else {
      return EMPTY;
    }
  }),
  // combine all emitted values into one array
  toArray()
)

Попробуйте пример оператора расширения

ПРИМЕЧАНИЕ: currentPage может протечь, поэтому будьте осторожны с этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...