VSO
VSO

Reputation: 12646

NG5 & RxJS: Make an Http Call on Load and Use the Data Once Available

I need to make a call in Angular 5 on app load and then use the returned data throughout the app. The goal is to pre-load the data. Later, I need to use the data immediately, or wait for it to load, without duplicating the call.

I believe I have achieved the desired functionality as shown in this plunk, but I didn't do it correctly at all. I just made the call and subscribed to it right away so the observable is hot. So, this is mistake one - not making the observable hot correctly.

Here is my code, note the commented parts:

  constructor(private http: Http) {
    const testUrl: string = 'http://httpbin.org/delay/3';
    this.vlData = this.http.get(testUrl)
      .map( (res) => res.json() ).publishReplay(1).refCount()
      .catch( (err) => Observable.throw(error.json().error) )
      //.publish();

//this.vlData.connect();

  this.vlData.subscribe(
  (next) => {console.log('INITIAL DATA RETURN: ', next)},
  (err) => {console.log(`ERR: ${err}`)});

}

THE QUESTION: Is this code "bad"? If so, how do I accomplish the same result using the commented out operators publish and connect? Do I need to here?

P.S. I have about 15 articles / SO posts on the topic open, none of them seem to help, or I don't get it.

Upvotes: 2

Views: 420

Answers (1)

Igor
Igor

Reputation: 62213

If you want to ensure that the data is cached after the first call then store the observable in a private field and return it after it has a value. The returned value(s) will resolve just the first time and be served up again on subsequent calls.

services/vl-data.service.ts (body code)

Note that this code was taken from the plunk link you posted, not the code posted in the question.

private _vlData: Observable<any>;

constructor(private http: Http) {}

getVlData(): Observable<any> {
    if(!this._vlData) {
        const testUrl: string = 'http://httpbin.org/delay/3';
        this._vlData = this.http.get(testUrl)
          .map( (res) => res.json() )
          .catch( (err) => Observable.throw(error.json().error) );
      }
    return this._vlData;
}

Some side notes:

  1. Try not to put any business logic or calls in your constructors, this makes them more difficult to test and ideally you want executions to occur explicitly instead of as a side effect of some other process (like when your service is created which you).
  2. You should consider using HttpClient instead of Http, the latter is considered obsolete/deprecated.
  3. You should consider using the RxJs pipable operators over the "older" patch operators.

Upvotes: 1

Related Questions