Reputation: 490
I have to make multiple API calls(http-requests) to get all the data I need.
Since I have to make 2 independent API calls that both should be finished with retrieving data, I am trying to sync to that.
I have nearly 0 experience in typescript/angular and couldn't find a solution via google.
Here are the API calls I'm making(signatures):
public supportedLanguages(observe?: 'body', reportProgress?: boolean): Observable<Array<string>>;
public getAllFilters(acceptLanguage?: string, observe?: 'body', reportProgress?: boolean): Observable<Array<Filter>>;
Here is the code I am currently using to fill Array<Type>
:
this.langService.supportedLanguages().subscribe(langs => setTimeout(() =>
this.langs.push(...langs), 1000));
this.categorieService.getAllFilters('de').subscribe(categories => setTimeout(() => {
this.categories.push(...categories), 1000));
I am guessing that this is not the right approach to retrieving the data, but I haven't found a better way(I am very new to typescript/angular).
What are the right steps to take to wait for said data to be loaded?
Upvotes: 2
Views: 4464
Reputation: 805
You could also just use a combination of async, await and promises.
First you'd have to append .toPromise()
to your service methods. Then in your component.ts file add the following method...
private async fetchData() {
return await Promise.all([
this.langService.supportedLanguages();
this.categoryService.getAllFilters();
]).then(res => {
this.langs.push(res[0]); //res[0] is data returned by API supportedLanguages
this.categories.push(res[1]); //res[1] is data returned by API getAllFilters
this.status = true; // Confirms that now you have all your data back
}
}
Call this.fetchData()
inside ngOnInit()
Then maybe you'd have a status variable that you'd initialize to false
and then set to true
once all the data has been returned.
Upvotes: 1
Reputation: 302
You can use
(I am using "rxjs": "^5.5.11").
forkJoin
import 'rxjs/add/observable/forkJoin';
import { Observable } from 'rxjs';
import { Subscription } from 'rxjs/Subscription';
/* Multiple Service calls are asynchronism. use forkJoin to group service calls */
Observable.forkJoin(
this.supportedLanguages();
this.getAllFilters()
).subscribe(
response =>{
//response[0] is data returned by API supportedLanguages
//response[1] is data returned by API getAllFilters
}
error => console.log("Error: ", error),
() =>{
//All the API calls are completed here. Put your code here
//codes should be executed after the completion of all API calls
}
)
Upvotes: 4
Reputation: 346
If you want call the API in same times and return in same times, you could use ForkJoin from rxjs, see about the documentation
forkJoin(
this.langService.supportedLanguages(),
this.categorieService.getAllFilters('de'))
).subscribe(x =>
console.log(x[0]); //result from api call 1
console.log(x[1]); //result from api call 2
)
but if you want call first api, then after first api finish, you want call the second api. you could use concatMap, see about documentation here, concat map used maybe when your second api, need parameter from first
this.langService.supportedLanguages().pipe(
concatMap(resultFromApi1 => this.categorieService.getAllFilters('de'))
).subscribe(x => console.log(x)) //x = result from api 2;
I have nearly 0 experience in typescript/angular and couldn't find a solution via google.
you must try different way, cause angular not only angular. like 'rxjs' and other.. you need know what library js you used. and carefully with version, cause the angular really - really confusing about version and have different because the structure writing is a little different
Upvotes: 0
Reputation: 22262
You can use ForkJoin from Rxjs 6:
import {forkJoin} from 'rxjs';
// ...
forkJoin(
this.langService.supportedLanguages(),
this.categorieService.getAllFilters('de'))
).subscribe([langs, categories] => {
// ...
})
OR, you can put the 2 API calls in a Promise:
function recoverData() {
return new Promise((resolve, reject) => {
this.langService.supportedLanguages().subscribe(langs => this.langs.push(...langs), 1000);
this.categorieService.getAllFilters('de').subscribe(categories => this.categories.push(...categories), 1000);
resolve();
});
}
And then you use it like that:
recoverData().then(() => {
// Some code
});
Upvotes: 0
Reputation: 3823
you can try forkJoin from rxjs:
forkJoin(
this.langService.supportedLanguages(),
this.categorieService.getAllFilters('de'))
)
.subscribe([langs, categories]=>{
...
})
Upvotes: 1