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.