0

Given the following code (test code), what is the best way to have only one call to the requested file? Currently, each time the button is pressed, a XHR request is done.

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';

@Injectable()
export class MyService {
    constructor(private http: Http) {}
    getList() {
        return this.http.get('./public/data.json')
            .map(res => res.json());
    }
    getOne(id: number) {
        return this.getList()
            .map(data => data.filter(my => my.id === id)[0]);
    }
}

Here's the json data file

[
    {"id": 1, "name": "Data 1"},
    {"id": 2, "name": "Data 2"},
    ...
]

Here is the component file. It uses a simple model file (which is only a class with id and name properties)

import {Component} from 'angular2/core';
import {MyService} from 'my-service';
import {MyModel} from 'my-model';

@Component({
    selector: 'test',
    templateUrl: `
        <button (click)="getRandom()">Test</button>
        <p>{{ selected.name }} ({{ selected.id }})</p>
    `
})
export class MyComponent {
    selected: MyModel;
    constructor(private myService: MyService) {}
    getRandom() {
        let id = Math.floor((Math.random() * 10) + 1);
        this.myService.getOne(id)
            .subscribe((data: MyModel) => this.selected = data);
    }
}

I'm not putting here all the stuff to bootstrap the application. But this shows the idea.

Many thanks

rekam
  • 1,061
  • 3
  • 13
  • 31

1 Answers1

8

You could leverage the do operator to cache the data received the first time within a service property:

@Injectable()
export class MyService {
  private data:any;

  constructor(private http: Http) {}

  getList() {
    if (this.data) {
      return Observable.of(this.data);
    } else {
      return this.http.get('./public/data.json')
        .map(res => res.json())
        .do(data => {
          this.data = data;
        });
    }
  }

  getOne(id: number) {
    return this.getList()
      .map(data => data.filter(my => my.id === id)[0]);
  }
}
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • I was missing the Observable.of concept. Thanks! – rekam Apr 05 '16 at 09:17
  • the best answer ever seen on stackoverflow. One thing left to understund please, what is the difference between do and subscribe ? – user2080105 Feb 08 '17 at 15:01
  • 1
    @user2080105 `do()` is run as a side effect of the observable ([docs](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-do)). It doesn't actually run until something else `subscribe()`s to the observable. – jessepinho Mar 02 '17 at 20:25