简体   繁体   中英

How to chain Http calls in Angular2?

I'm new to Angular2 and Http Observable. I have a component which calls Http service and returns Observable. Than I subscribe to that Observable and it works fine.

Now, I want,in that component, after calling first Http service,if call is success, call other Http service and return that Observable. So, if first call is not success the component returns that Observable, opposite it returns Observable of second call.

So, question is, what is the best way to chain Http calls? Is there any elegant way, for example like monads?

You can do this using the mergeMap operator.

Angular 4.3+ (using HttpClientModule ) and RxJS 6+

import { mergeMap } from 'rxjs/operators';

this.http.get('./customer.json').pipe(
  mergeMap(customer => this.http.get(customer.contractUrl))
).subscribe(res => this.contract = res);

Angular < 4.3 (using HttpModule ) and RxJS < 5.5

Import the operators map and mergeMap , then you can chain two calls as follows:

import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/mergeMap';

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);

Some more details here: http://www.syntaxsuccess.com/viewarticle/angular-2.0-and-http

More information about the mergeMap operator can be found here

Using rxjs to do the job is a pretty good solution. Is it easy to read ? I don't know.

An alternative way to do this and more readable (in my opinion) is to use await/async .

Example :

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
}

Then call it :)

this.myService.getContrat().then( (contract) => {
  // do what you want
});

or in an async function

const contract = await this.myService.getContrat();

You can also use try/catch to manage error :

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
}

You could also chain Promises too. Per this example

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM