I am making an Angular 4 app. Components are subscribing Observable. Sometimes Observable call the same url. For example 'refresh Access Token' if needed before any http request. But if I make different 3 http requests, it will "refresh if needed" 3 times the refresh token.
So how to make only one http get to get a refreshed access token, and make the other observables 'wait' for the first one ? (I know 'wait' is not the good word for Observables).
public get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.getAccessToken().mergeMap(accessToken => {
return this.http.get(url, options);
});
}
// And
this.get('www.myapi.com/one').subscribe(data=>console.log('one',data))
this.get('www.myapi.com/two').subscribe(data=>console.log('two',data))
this.get('www.myapi.com/three').subscribe(data=>console.log('three,data))
It seems like you can use the share()
operator that makes sure there's always only one subscription to the source Observable.
However this will require you to restructure your code because all observers need to use the same instance of share()
:
const sharedToken = this.getAccessToken().share();
public get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return sharedToken.mergeMap(accessToken => {
return this.http.get(url, options);
});
}
Use an operator called forkJoin. If you are familiar with Promises this is very similar to Promise.all(). The forkJoin() operator allows us take a list of Observables and execute them in parallel. Once every Observable in the list emits a value the forkJoin with emit a single Observable value containing a list of all the resolved values from the Observables in the list
please go through the below example:
Import:
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/forkJoin';
Let assume you have to get three pages
var pages:number[] = [1, 2, 3];
Or var pages:number[]=new Array(10).fill().map((v,i)=>i+1);
and then map them into an array of observables and forkJoin
Observable.forkJoin(
pages.map(
i => this.http.get('www.myapi.com/' + i)
.map(res => res.json())
)
).subscribe(people => this.people = people);
Please go Stack or forkJoin for more info.