0

I want to cache my data, but at the same time I need my data to be up-to-date. I found this: Angular2 easiest way to cache HTTP responses but this will not check for new data.

I have this now in my service:

public publishedSessions: Session[] = null;

  getPublishedSessions(): Observable<any> {
    let headers = new Headers();
    headers.append('authorization', this.userService.getToken());

    if (this.publishedSessions) {
      this.http.get(this.apiUrl + 'api/sessions/published', {
        headers: headers
      })
        .map(res => res.json().sessions)
        .subscribe(sessions => this.publishedSessions = sessions);

      return Observable.of(this.publishedSessions);
    } else {
    return this.http.get(this.apiUrl + 'api/sessions/published', {
      headers: headers
    })
      .do(res => this.publishedSessions = res.json().sessions)
      .map(res => res.json().sessions)
      .catch((error) => Observable.of(error));
    }
  }

And some standard code in my component:

handlePublishedSessions(): void {
     this.subscriptionArr.push(this.sessionService.getPublishedSessions().subscribe(sessions => {
      this.session = sessions
  }));
}

This causes the effect that when I first navigate (visit 1) to the page, a call (call 1) will be made (wanted). Then if I navigate away and return back to the page (visit 2), the data from call 1 will be returned (not wanted), in the meantime, call 2 is in the works. So if I then navigate away again and navigate back (visit 3), the data from call 2 is being returned.

I want that the call 1 data is displayed on visit 2 for the first few milliseconds (untill call 2 is done). When call 2 is done I want the data to be replaced (without user interaction).

Community
  • 1
  • 1
stijn.aerts
  • 6,026
  • 5
  • 30
  • 46
  • What behavior would you expect on the second visit? You WANT the cached data.. do you want that cached data AND want to be notified if the second request is finished? Please explain what you want :) – slaesh Sep 22 '16 at 07:38
  • Spot on! I have edited the question: I want that the call 1 data is displayed on visit 2 for the first few milliseconds (untill call 2 is done). When call 2 is done I want the data to be replaced (without user interaction). – stijn.aerts Sep 22 '16 at 07:42

1 Answers1

1

I would use a BehaviorSubject to cache data.

Take a look at this plunker to get an idea: https://plnkr.co/edit/jNNQJToYia2MhIE488YX?p=preview

import {Component, NgModule, Injectable} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {HttpModule, Http} from '@angular/http';

import {BehaviorSubject} from 'rxjs/Rx';

@Injectable()
export class AnyService {

  public data = new BehaviorSubject<string>();

  constructor(private _http: Http) { }

  public getData(): string {
    this._http.get('https://httpbin.org/bytes/12')
      .subscribe(
        resp => this.data.next(resp._body)
      );
    return this.data.value;
  }
}

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2 (click)="getData()">Hello {{name}} -- CLICK ME !! --</h2>
    </div>
  `,
})
export class App {
  name:string;

  firstSubscribeCallback = false;

  constructor(private _srvc: AnyService) {
    this.name = 'Angular2'

    this._srvc.data.subscribe(
      newData => {

        // FIRST CALL WILL BE THE CACHED DATA..
        if (!this.firstSubscribeCallback) { // JUST FOR DEMO ..

          console.log('got cached data @ startup..');
          this.firstSubscribeCallback = true;

        }
        else console.log('got new data:');

        console.log(newData);
      }
    );

    this.getData(); // get FRESH data ..
  }

  getData() {
    console.log('getting cached data:');
    console.log(this._srvc.getData());
  }
}

@NgModule({
  imports: [ BrowserModule, HttpModule ],
  declarations: [ App ],
  providers: [ AnyService ],
  bootstrap: [ App ]
})
export class AppModule {}
slaesh
  • 16,659
  • 6
  • 50
  • 52