NoIdeaHowToFixThis
NoIdeaHowToFixThis

Reputation: 4564

Consume Json file from Service in Angular 2

I have a service. In the constructor:

export class Service {

  _data: any

  constructor(private http: Http) {
    this.http
      .get('../assets/my_json_file.json')
      .map(x => x.json() )
      .subscribe( (data) => 
        this._data = data
      )
    console.log(this._data)
  }

The console.log returns undefined although it does show data if the console.log is moved into the function passed to subscribe.

My goal is to have a number of functions getStuff() in the service, callable by the app at ngOnInit with values for dropdown menus and stuff

Seen this but did not help figure out what went wrong

Upvotes: 3

Views: 6386

Answers (1)

Günter Zöchbauer
Günter Zöchbauer

Reputation: 657118

this.http.get('../assets/my_json_file.json') is async, which means that a call to the server is scheduled for later execution and when the response from the server arrives eventually the callback passed to .subscribe(...) will be called with the response. "scheduled" means a task will be added to the event queue for later execution when the previously scheduled tasks are done.

After the http.get(...) call is scheduled console.log(this._data) will be executed. This is before the call to the server is even initiated.

The http.get(...) call is also only scheduled when the observable returned by http.get(...) is subscribed to because observables are lazy.

Using map(...) instead of subscribe(...) returns an Observable instead of a Subscription which allows the user of your service to chain it's own code to response events.

@Injectable()
export class Service {

  _data: any

  constructor(private http: Http) {}

  getData() {
    this.http
      .get('../assets/my_json_file.json')
      .map(x => x.json() )
      .map( (data) => 
        this._data = data
      )
    console.log(this._data)
  }
}

In a component you can use it like

export class MyComponent {
  constructor(service:Service) {
    // `subscribe` actually initiates the call to the server
    service.getData().subscribe(result => console.log(result));
  }
}

See also What is the correct way to share the result of an Angular 2 Http network call in RxJs 5?

This way you can already initiate the call to the server when the service is instantiated, not only after the component that uses the service subscribes.

Upvotes: 6

Related Questions