Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 RxJS calling class function from map function

I'm new to Angular 2 and Observables so I apologise if my problem is trivial. Anyway I'm trying to test the Angular 2 HTTP Client using RxJS. Although I got it to work I need to add more logic to the service I'm currently working on. Basically I'd like to have a mapping function to convert the object I receive from the web service I'm connected to, to the model object I have in Angular.

This is the code that works:

import { Injectable } from 'angular2/core';
import { Http, Response } from 'angular2/http';
import { Observable } from 'rxjs/Observable';

import { Person } from '../models/person';

@Injectable()
export class PersonsService {

    constructor(private http: Http) { }

    private personsUrl = 'http://localhost/api/persons';

    getPersons(): Observable<Person[]> {
        return this.http.get(this.personsUrl)
            .map(this.extractData)
            .catch(this.handleError);
    }

    private extractData(res: Response) {
        if(res.status < 200 || res.status >= 300) {
            throw new Error('Bad response status ' + res.status);
        }

        let body = res.json();
        return body.data || {};
    }

    private handleError(error: any) {
        let errMsg = error.message;
        return Observable.throw(errMsg);
    }
}

With the above code I have no problems whatsoever. The issue I'm having is that I'd like to map the object I'm getting from the service to the one I have in Angular i.e. Person. What I tried is to call another function from the extractData function that's being used by the .map function.

private extractData(res: Response) {
    if(res.status < 200 || res.status >= 300) {
        throw new Error('Bad response status ' + res.status);
    }

    let body = res.json();
    // map data function
    var data = this.mapData(body.data);

    return data || {};
}

private mapData(data: any) {
    // code to map data
}

Obviously the code above doesn't work as when this is referenced inside the extractData function, this does not refer to the PersonsService class, but it refers to a MapSubscriber object.

I don't know if it is possible to call an "external" function. It might be a silly thing but I can't find any information regarding this.

like image 798
Daniel Grima Avatar asked May 13 '16 18:05

Daniel Grima


2 Answers

Instead of just passing the function reference use arrow functions to retain this

.map((res) => this.extractData(res))
like image 75
Günter Zöchbauer Avatar answered Nov 15 '22 18:11

Günter Zöchbauer


Observable's map function allows you to pass a reference variable as a second argument on how should this actually work inside the higher-order function.
so the solution is
.map(this.extractData,this)
This way while passing the extractData function you are also passing the current class's this execution context to the higher-order function. It will work.

Observable Doc Reference Link

screenshot of the doc

like image 45
Saisurya Kattamuri Avatar answered Nov 15 '22 19:11

Saisurya Kattamuri