Angular2 http.get() ,map(), subscribe() and observable pattern - basic understanding

nyks picture nyks · Jan 8, 2016 · Viewed 373.4k times · Source

Now, I have an initial page where I have three links. Once you click on the last 'friends' link, appropriate friends Component gets initiated. In there, I want to fetch/get list of my friends strored into friends.json file. Till now everything works fine. But I'm still a newbie for angular2's HTTP service using RxJs's observables, map, subscribe concept. I've tried to understand it and read few articles but until I get into practical work, I'm not gonna understand those concepts properly.

Here I have already made plnkr which is working except HTTP related work.

Plnkr

myfriends.ts

 import {Component,View,CORE_DIRECTIVES} from 'angular2/core';
 import {Http, Response,HTTP_PROVIDERS} from 'angular2/http';
 import 'rxjs/Rx';
 @Component({
    template: `
    <h1>My Friends</h1>
    <ul>
      <li *ngFor="#frnd of result">
          {{frnd.name}} is {{frnd.age}} years old.
      </li>
    </ul>
    `,
    directive:[CORE_DIRECTIVES]
  })

  export class FriendsList{

      result:Array<Object>; 
      constructor(http: Http) { 
        console.log("Friends are being called");

       // below code is new for me. So please show me correct way how to do it and please explain about .map and .subscribe functions and observable pattern.

        this.result = http.get('friends.json')
                      .map(response => response.json())
                      .subscribe(result => this.result =result.json());

        //Note : I want to fetch data into result object and display it through ngFor.

       }
  }

Please guide and explain properly. I know it will be so beneficial to lots of new developers.

Answer

Abdulrahman Alsoghayer picture Abdulrahman Alsoghayer · Jan 8, 2016

Here is where you went wrong:

this.result = http.get('friends.json')
                  .map(response => response.json())
                  .subscribe(result => this.result =result.json());

it should be:

http.get('friends.json')
                  .map(response => response.json())
                  .subscribe(result => this.result =result);

or

http.get('friends.json')
                  .subscribe(result => this.result =result.json());

You have made two mistakes:

1- You assigned the observable itself to this.result. When you actually wanted to assign the list of friends to this.result. The correct way to do it is:

  • you subscribe to the observable. .subscribe is the function that actually executes the observable. It takes three callback parameters as follow:

    .subscribe(success, failure, complete);

for example:

.subscribe(
    function(response) { console.log("Success Response" + response)},
    function(error) { console.log("Error happened" + error)},
    function() { console.log("the subscription is completed")}
);

Usually, you take the results from the success callback and assign it to your variable. the error callback is self explanatory. the complete callback is used to determine that you have received the last results without any errors. On your plunker, the complete callback will always be called after either the success or the error callback.

2- The second mistake, you called .json() on .map(res => res.json()), then you called it again on the success callback of the observable. .map() is a transformer that will transform the result to whatever you return (in your case .json()) before it's passed to the success callback you should called it once on either one of them.