RxJS Pagination Observable
tout d'abord: C'est le premier projet dans lequel J'utilise RxJs, j'ai pensé que j'apprendrai mieux en l'utilisant.
j'ai trouvé cette réponse: transformer les requêtes paginées en un flux Observable avec RxJs Mais il est dit dans les commentaires:
vous dépassez toujours la pile d'appels maximale. Environ 430 pages retournées. Je pense que la récursivité peut-être pas la meilleure solution ici
je veux interroger L'API de données Youtube, les résultats viennent retour dans les pages et je dois paginer à travers eux. J'ai imaginé un flux de travail comme cela pourrait fonctionner: 1)Lancer un appel 2) Vérifiez si la réponse a un "nextPageToken" 3)si c'est le cas, faites une autre requête à L'API Youtube 4) si non, terminer
So to do this I could Imagine the following Observables / streams:
FirstRequestStream -A-X--------------->
ResponseStream -A-A-A-A--X-------->
RequestStream -I-A-I-A----------->
A = Action
I = Info from upper stream
X = Termination
(Je ne suis pas sûr que ce diagramme soit correct de la façon dont je l'ai fait)
ainsi la réponse dépend de FirstRequestStream et RequestStream (en utilisant la fonction de fusion). Le flux request dépend de la réponse (est-ce que cela s'appelle un circulation observables ?)
-Est-ce la bonne solution ?
-les "observables circulants" sont-ils une bonne chose, sont-ils même possibles ?(J'ai eu des problèmes pour la création d'un).
-un autre moyen que je devrais essayer en premier?
- est-il possible de créer des flux observables interdépendants ?
Merci pour votre aide.
1 réponses
vous surchargez ce problème, il peut être résolu beaucoup plus facilement en utilisant l'opérateur defer.
L'idée est que vous créez observable différé (donc il sera créé et commencer à récupérer des données seulement après l'abonnement) et concaténez-le avec le même observable mais pour la page suivante, qui sera également concaténée avec la page suivante, et ainsi de suite ... . Et tout cela peut se faire sans récursion.
Voici comment le code regarde:
const { defer, from, concat, EMPTY, timer } = rxjs; // = require("rxjs")
const { mergeMap, take, mapTo, tap } = rxjs.operators; // = require("rxjs/operators")
// simulate network request
function fetchPage(page=0) {
return timer(100).pipe(
tap(() => console.log(`-> fetched page ${page}`)),
mapTo({
items: Array.from({ length: 10 }).map((_, i) => page * 10 + i),
nextPage: page + 1,
})
);
}
const getItems = page => defer(() => fetchPage(page)).pipe(
mergeMap(({ items, nextPage }) => {
const items$ = from(items);
const next$ = nextPage ? getItems(nextPage) : EMPTY;
return concat(items$, next$);
})
);
// process only first 30 items, without fetching all of the data
getItems()
.pipe(take(30))
.subscribe(e => console.log(e));
<script src="https://unpkg.com/rxjs@6.2.2/bundles/rxjs.umd.min.js"></script>