简体   繁体   中英

RxJs: Share an Observable using async / await

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.

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