web-dev-qa-db-fra.com

Comment chaîner des appels HTTP dans Angular2?

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?

52
zlaja

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

82
TGH

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
}
3
xrobert35

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>
0
JGFMK