Je suis nouveau sur Angular2 et Http Observable. J'ai un composant qui appelle le service HTTP et renvoie Observable. Que je souscrive à cet observable et cela fonctionne bien.
Maintenant, je veux, dans ce composant, après avoir appelé le premier service HTTP, si l’appel aboutit, appeler un autre service HTTP et renvoyer cet observable. Ainsi, si le premier appel n'aboutit pas, le composant renvoie cet observable, alors qu'il renvoie l'observable du second appel.
La question est donc de savoir quel est le meilleur moyen de chaîner les appels HTTP. Y a-t-il une manière élégante, par exemple comme des monades?
Vous pouvez le faire en utilisant l'opérateur mergeMap
Commencez par importer l'opérateur comme suit:
import 'rxjs/add/operator/mergeMap';
Alors voici comment vous enchaînez deux appels:
this.http.get('./customer.json')
.map((res: Response) => res.json())
.mergeMap(customer => this.http.get(customer.contractUrl))
.map((res: Response) => res.json())
.subscribe(res => this.contract = res);
Quelques détails supplémentaires ici: http://www.syntaxsuccess.com/viewarticle/angular-2.0-and-http
Vous trouverez plus d’informations sur l’opérateur mergeMap ici
Utiliser rxjs pour faire le travail est une très bonne solution. Est-ce facile à lire? Je ne sais pas.
Une autre façon de le faire et plus lisible (à mon avis) est d’utiliser wait/async .
Exemple :
async getContrat(){
//get the customer
const customer = await this.http.get('./customer.json').toPromise();
//get the contract from url
const contract = await this.http.get(customer.contractUrl).toPromise();
return contract; // you can return what you want here
}
Alors appelle ça :)
this.myService.getContrat().then( (contract) => {
// do what you want
});
ou dans une fonction asynchrone
const contract = await this.myService.getContrat();
Vous pouvez également utiliser try/catch pour gérer les erreurs:
let customer;
try {
customer = await this.http.get('./customer.json').toPromise();
}catch(err){
console.log('Something went wrong will trying to get customer');
throw err; // propagate the error
//customer = {}; //it's a possible case
}
Vous pouvez également enchaîner les promesses. Par cet exemple
<html>
<head>
<meta charset="UTF-8">
<title>Chaining Promises</title>
</head>
<body>
<script>
const posts = [
{ title: 'I love JavaScript', author: 'Wes Bos', id: 1 },
{ title: 'CSS!', author: 'Chris Coyier', id: 2 },
{ title: 'Dev tools tricks', author: 'Addy Osmani', id: 3 },
];
const authors = [
{ name: 'Wes Bos', Twitter: '@wesbos', bio: 'Canadian Developer' },
{ name: 'Chris Coyier', Twitter: '@chriscoyier', bio: 'CSS Tricks and Codepen' },
{ name: 'Addy Osmani', Twitter: '@addyosmani', bio: 'Googler'},
];
function getPostById(id) {
// create a new promise
return new Promise((resolve, reject) => {
// using a settimeout to mimic a database/HTTP request
setTimeout(() => {
// find the post we want
const post = posts.find(post => post.id == id);
if (post) {
resolve(post) // send the post back
} else {
reject(Error('No Post Was Found!'));
}
},200);
});
}
function hydrateAuthor(post) {
// create a new promise
return new Promise((resolve, reject) => {
// using a settimeout to mimic a database/http request
setTimeout(() => {
// find the author
const authorDetails = authors.find(person => person.name === post.author);
if (authorDetails) {
// "hydrate" the post object with the author object
post.author = authorDetails;
resolve(post);
} else {
reject(Error('Can not find the author'));
}
},200);
});
}
getPostById(4)
.then(post => {
return hydrateAuthor(post);
})
.then(post => {
console.log(post);
})
.catch(err => {
console.error(err);
});
</script>
</body>
</html>