Comment pouvons-nous aplatir au mieux les appels ci-dessous. Nouveau sur RxJS, essayant de comprendre comment il devrait être simplifié. Lisez flatMap, forkJoin, switchMap et mergeMap, sans trouver le bon chemin pour l'intégrer ci-dessous et ne pas savoir ce qui est le meilleur dans le scénario ci-dessous.
const useful = []; a.get('abc'). subscribe((abcdatas) => { abcdatas.forEach(abcdata => { if(abcdata.exist) { b.get('def'). subscribe((defdatas) => { useful.push(defdatas.someval); }); } }); }) if(useful.length) { c.get('ghi'). subscribe((ghidata) => { completed... }); }
Mise à jour de ma question ici et merci pour toutes les réponses. L'utile est un tableau global de résultats qui devrait être rempli à partir d'un appel imbriqué dans mon cas. Et il devrait être passé au dernier appel enfin.
Étapes que j'essaye:
3 Réponses :
Utilisez une fonction de mappage telle que switchMap
ou mergeMap
pour mapper le résultat d'une demande à la demande suivante. Utilisez forkJoin
pour exécuter plusieurs requêtes simultanément.
Donc, pour un scénario un à plusieurs, l'idée générale est:
useful = []; a.get('abc').pipe( switchMap(abcdatas => forkJoin(getUseFulRequests(abcdatas))), tap(useful => useful.forEach(u => this.useful.push(u))), switchMap(useful => useful.length ? c.get('ghi') : EMPTY) ).subscribe((ghidata) => { completed... }); function getUseFulRequests(abcdatas: AbcData[]): Observable<SomeVal>[] { return abcdatas.reduce((acc, abcdata) => { if (abcdata.exist) { const request = b.get('def').pipe( map(defdatas => defdatas.someval) ) acc.push(request); } return acc; }, []); }
Pour votre cas, ce serait quelque chose comme:
firstRequest().pipe( switchMap(results => forkJoin(results.map(r => nextRequest(r)))) )
Cela n'émettra rien si getUseFulRequests(abcdatas)
renvoie un tableau vide ou useful.length == 0
.
Appréciez votre réponse
utile n'est pas seulement pour les requêtes utiles, c'est un tableau formé par le deuxième appel ibget ()
@MithunShreevatsa vous pouvez utiliser tap
pour remplir votre tableau global à partir d'une réponse intermédiaire.
Exemple s'il vous plaît, comme je l'ai dit, je suis nouveau et cela prend du temps pour moi de sortir d'axios et d'async, d'attendre et de promettre
merci, j'ai appris quelque chose de très utile de votre réponse et m'appelle clairement :)
Je pense que la meilleure façon de gérer cela sera d'utiliser des observables d'ordre supérieur
Considérez ci-dessous le code
useful$ = a.get('abc').pipe( mergeMap(abcdatas => abcdata.exist ? forkJoin(abcdatas.map(abcdata => b.get('def'))) : of(undefined) ), map(defdatas => defdatas.flat()), mergeMap(({ length }) => length ? c.get('ghi') : of(undefined)) ); useful$.subscribe({ next: () => { // Completed... } })
Nous a.get('abc')
abord le résultat de a.get('abc')
et utilisons mergeMap pour tester si abcdata.exist
. S'il sort, nous retournons forkJoin(abcdatas.map(abcdata => b.get('def')))
simplement cela combinera un tableau d'observables générés à partir de la fonction map sur abcdatas
map(defdatas => defdatas.flat()),
transformera le tableau en un seul tableau REMARQUE: flat () a été introduit dans ES2019
Ensuite, nous déstructurons la propriété length
et si elle existe, nous retournons notre observable finale
Appréciez votre réponse
Je pense que ce que vous essayez de faire est ceci:
a.get("abc").pipe( mergeMap((abcdatas) => abcdatas.filter((abcdata) => abcdata.exist)), // let's create a stream with all those useful abcdata mergeMap(abcdata => b.get('def')), // and for each one of those we perform a b.get request toArray(), // once all the b.get requests have completed, emit a one value stream with an Array of those values values concatMap(useful => useful.length ? c.get('ghi') : EMPTY) // let's concat that result with the final request )
Appréciez votre réponse