4

I'm new to Angular and following this tutorial to learn the basics. Consider the following http get call.

getHeroes(): Promise<Hero[]> {
    return this.http.get(this.heroesUrl)
               .toPromise()
               .then(response => response.json().data as Hero[])
               .catch(this.handleError);
  }

After converting the observable to a promise, how can I really utilize the response(e.g. console log, parse and access a response element.. etc) using a function inside the then() clause?

I tried the following, even though it logs the Response, I can't really access anything in the response object.

this.http.get(url, {headers : this.headers})
                        .toPromise()
                        .then(function(res) {
                                console.log(res);
                                return res => res.json().data as Query[];
                        })
                        .catch(this.handleError);

Any help would be much appreciated. Thank you.

DilumN
  • 2,889
  • 6
  • 30
  • 44
Maddy
  • 2,114
  • 7
  • 30
  • 50
  • 1
    What do you needto access from the response could you describe it in more detail. And I would suggest to use Observables instead of promises. Observables can be canceled etc. Have a look at this post and decide then: http://stackoverflow.com/questions/37364973/angular-2-promise-vs-observable – blacksheep_2011 Feb 16 '17 at 07:00
  • thanks. let's say this calls a web service that returns a User object and I want to fetch a name from the response. – Maddy Feb 16 '17 at 07:07
  • what did you get in the `response` can you paste that in the question? – Sravan Feb 16 '17 at 07:18

3 Answers3

3

Angular2 use RXjs observable instead of promises. It work as follows.

create httpService as follows.

httpService.ts

import {Injectable, Inject} from '@angular/core';
import {Http, Response, RequestOptions, Request, Headers} from '@angular/http';

declare let ApiUrl : any;

@Injectable()
export class httpService {
    constructor(private http: Http){}

    getHeader = () => {
        let headers = new Headers();
        headers.append("Content-Type", 'application/json');

        return headers;
    };

    request = (req) => {
        let baseUrl = ApiUrl,
            requestOptions = new RequestOptions({
            method: req.method,
            url: baseUrl+req.url,
            headers: req.header ? req.header : this.getHeader(),
            body: JSON.stringify(req.params)
        });

        return this.http.request(new Request(requestOptions))
                        .map((res:Response) => res.json());
    }
}

Now simply use this service in your components/directives as below:

componenet.ts

import {Component, Inject, Directive, Input, ElementRef} from '@angular/core';

@Directive({
  selector: '[charts]' // my directive name is charts
})
export class chartsDirective{

  constructor(@Inject('httpService') private httpService){}

  ngOnInit(){

    this.httpService.request({method: 'POST', url: '/browsers', params:params, headers: headers})
            .subscribe(
                data => self.data = data, //success
                error => console.log('error', error),
                () => {console.log('call finished')}
            )
  }
}

And lastly you justt need to add your httpService to provider of ngModule:

appModule.ts

import {NgModule} from '@angular/core';
import {ApiService} from "./api.service";

@NgModule({
    providers: [
        {provide : 'httpService', useClass : httpService}
    ]
})

export class apiModule{}

Now, You can use httpService anywhere in your code by injecting like we did in component.ts

jigar gala
  • 1,600
  • 12
  • 20
  • 2
    `http.get()` returns an Observable, but he transforms it to a Promise using the rxjs `toPromise()` funtion. This is perfectly OK in Angular2 so there is absolutely no need to refactor all his code. – Nico Van Belle Feb 16 '17 at 08:28
  • @NicoVanBelle Yeah I got that, the reason behind re-writing was to make him understand how it can be implemented with best practices. – jigar gala Feb 16 '17 at 09:55
  • @jigargala can you please explain why your code is best practice over his? – Xin Aug 10 '17 at 14:02
  • 1
    @Xin he was trying to convert the observable to promise which is not required. Observable is one kind of promise only. Other than that code is structured and Modularize. Do let me know if you think I can update anything more in mine answer. – jigar gala Aug 10 '17 at 14:44
  • 1
    @jigargala observables in the context of an HTTP request make no semantic sense. A request is something that has a beginning and has an end. Observables are ongoing streams of data. So no, using observables here it's not a best practice. – Joel Hernandez Sep 20 '17 at 11:52
  • @JoelHernandez But Observable has many advantages over promises so it is up to the choice of a programmer. – jigar gala Sep 20 '17 at 12:29
  • 1
    Agreed, the programmer can choose to write clean and meaningful code or have the *possibility* of using dozens of features. – Joel Hernandez Sep 20 '17 at 12:42
  • https://netbasal.com/angular-stop-using-observable-when-you-should-use-a-promise-8da0788a8d2 – Joel Hernandez Sep 20 '17 at 12:55
1

here an example of how you can do it.

Not necessary but gives a nice code structure create a service which handles all your user requests:

User Service

@Injectable()
export class UserService {

   constructor(private http: Http) { }

   getById(id: string): Observable<User> {
      return this.http.get("http://127.0.0.1" + '/api/CustomUsers/' + id)
      // ...and calling .json() on the response to return data
      .map((res: Response) => {
         var user = User.withJSON(res.json());
         return user;
      })
      //...errors if any
      .catch((error: any) => Observable.throw(error));
   }
}

So here we fetch the user with a given id and creates a user object with the returned json.

User Model

export class User {

    constructor(public id: string, public username: string, public email: string) {

    }

    static withJSON(json: any): User {

        // integrity check
        if (!json || !json.id || !json.username || !json.email) { return undefined; }

       var id = json.id;
       var username = json.username;
       var email = json.email;

       // create user object
       var user = new User(id, username, email);
       user.firstname = firstname;

       return user;
   }

Service call

this.userService.getById(this.id).subscribe(user => {
    this.user = user;
  },
    err => {
       console.error(err);
    });

Hope this helps

blacksheep_2011
  • 1,083
  • 3
  • 11
  • 22
0

I had a similar issue. After debugging the response object I found that data did not exist on the res.json() object. Change to this instead:

this.http.get(url, {headers : this.headers})
                    .toPromise()
                    .then(function(res) {
                            console.log(res);
                            return res => res.json() as Query[];
                    })
                    .catch(this.handleError);

Notice all I did was change the line that reads return res => res.json().data as Query[];

to return res => res.json() as Query[];

nathanjessen
  • 1,008
  • 8
  • 8