Le chaînage des Observables dans l'ordre, que vous voulez faire dans votre code
Concernant votre exemple de code, si vous voulez de la chaîne d'Observables (en déclencher un autre après la précédente émet), utilisez flatMap
(ou switchMap
) à cet effet :
this.serviceA.get()
.flatMap((res1: any) => this.serviceB.get())
.flatMap((res2: any) => this.serviceC.get())
.subscribe( (res3: any) => {
....
});
C'est mieux de la pratique par rapport à la nidification, car cela va rendre les choses plus claires et vous aider à éviter de rappel de l'enfer, que les Observables et les Promesses étaient censés aider à prévenir en premier lieu.
Aussi, envisager l'utilisation d' switchMap
au lieu de flatMap
, fondamentalement, il permettra à "annuler", les autres demandes si le premier émet une nouvelle valeur. Agréable à utiliser si le premier Observables qui déclenche le reste est certains événement de clic sur un bouton, par exemple.
Si vous n'avez pas besoin de vos diverses demandes d'attente, tour à tour, les uns les autres, vous pouvez utiliser forkJoin
ou zip
pour démarrer tout à la fois, voir @Dan Macak réponse pour plus de détails et d'autres idées.
Angulaire 'async' pipe et Observables de bien travailler ensemble
Concernant les phénomènes Observables et Angulaire, vous pouvez parfaitement utiliser | async
pipe dans un Angulaires du modèle plutôt que de souscrire à l'Observable dans votre code de composant, pour obtenir la valeur(s) émis par cet Observable
ES6 async / await et des Promesses plutôt que des Observables ?
si vous ne vous sentez pas à l'aide Observable directement, vous pouvez simplement utiliser .toPromise()
sur votre Observables, et puis certains async/await instructions.
Si votre Observable est censé retourner qu'un seul résultat (comme c'est le cas de la base d'appels d'API) , Observable peut être considéré comme tout à fait équivalent à une Promesse.
Cependant, je ne suis pas sûr qu'il y est besoin de le faire, compte tenu de toutes les choses qui Observables déjà fournir (pour les lecteurs : en éclairant les contre-exemples sont les bienvenus!) . Je serais plus en faveur de l'utilisation des Observables à chaque fois que vous pouvez, comme un exercice d'entraînement.
Intéressant article de blog sur ce qui (et il y en a beaucoup d'autres):
https://medium.com/@benlesh/rxjs-observable-interop-with-promises-and-async-await-bebb05306875
Le toPromise fonction est en fait un peu délicat, car il n'est pas
vraiment un "opérateur", c'est plutôt un RxJS spécifique des moyens de
en souscrivant à un fait Observable et l'envelopper dans une promesse. La promesse
permettra de résoudre à la dernière émise valeur de l'Observable, une fois la
Observables complète. Cela signifie que si l'Observable émet l'
la valeur "bonjour", puis attend 10 secondes avant la fin, le retour de l'
promesse d'attendre 10 secondes avant de résoudre "salut". Si l'Observable
ne se termine jamais, alors, la Promesse n'a jamais résolu.
REMARQUE: l'utilisation de toPromise() est un antipattern sauf dans le cas où vous êtes
traiter avec une API qui s'attend à une Promesse, comme async-attendent
(l'emphase est mienne)
L'exemple que vous avez demandé
BTW, ça serait sympa si quelqu'un peut me donner un exemple de code pour résoudre
ce avec async/await :D
Exemple, si vous avez vraiment envie de le faire (probablement avec quelques erreurs, ne peut pas vérifier, dès maintenant, n'hésitez pas à corriger)
// Warning, probable anti-pattern below
async myFunction() {
const res1 = await this.serviceA.get().toPromise();
const res2 = await this.serviceB.get().toPromise();
const res3 = await this.serviceC.get().toPromise();
// other stuff with results
}
Dans le cas où vous pouvez commencer à toutes les demandes simultanément, await Promise.all()
qui devrait être plus efficace, car aucun des appels dépend de la suite les uns des autres. (comme le ferait forkJoin
faire avec Observables)
async myFunction() {
const promise1 = this.serviceA.get().toPromise();
const promise2 = this.serviceB.get().toPromise();
const promise3 = this.serviceC.get().toPromise();
let res = await Promise.all([promise1, promise2, promise3]);
// here you can promises results,
// res[0], res[1], res[2] respectively.
}