Using RxJs 5 and Angular 4.
I want to share an observable so that I only make 1 Http request, and I also want to await the calls so that I get the result when I request it. I have the following code:
export class DataService {
constructor(public http: HttpClient) {
this.getObservable();
}
public observable;
public getObservable() {
const url = "api/getData";
this.observable = this.http.get(`${this.baseUrl}${url}`).share()
}
public async hasData(data: DataEnum) {
const result = await this.observable.toPromise();
return result.filter(x => x === data).length > 0;
}
}
However many calls to hasData is resulting in many calls to our api end point. I am assuming that I have set observable
to a shared observable, and when I call .toPromise()
it will just get the cached value and make it a promise, which I can await
.
Is this how it should work?
Your code seems overly complex to me. I would likely do something like:
private data = null;
getData():Observable<> {
// if data is already available, return it immediately
if (this.data) return Observable.of(this.data);
// else, fetch from the server and cache result
return this.http.get(url).do(data => this.data=data)
}
So whenever you want the data you just do:
this.getData().subscribe(
data => console.log(data);
)
To be sure that you won't call your API endpoints multiple times before the data arrives, you have a few options.
Look into data resolvers -- these will not init your component until the data has arrived. In ngOnInit
the data will be ready synchronously so no risk of calling the server multiple times.
Alternatively, you can hide the view until the data is ready with *ngIf="data"
so a user won't click a button multiple times.
Due to how share
works, observable
is resubscribed on toPromise
, ths produces new requests.
Promises already provide caching behaviour. Considering that promises are already using in service API, they can be used exclusively:
constructor(public http: HttpClient) {
this.getPromise();
}
public promise;
public getPromise() {
const url = "api/getData";
this.promise = this.http.get(`${this.baseUrl}${url}`).toPromise()
}
public async hasData(data: DataEnum) {
const result = await this.promise;
return result.filter(x => x === data).length > 0;
}
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.