4

Here is my service TypeScript file.

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

@Injectable()
export class CarService {
    constructor(private http: Http) { }
    Url: string = 'url/of/api';
    getCar(){
        var headers = new Headers();
            headers.append('API-Key-For-Authentification', 'my_own_key_goes_here');
            headers.append('Accept', 'application/json');
        var options = new RequestOptions({ headers: headers })
        return this.http.get(this.Url, options)
            .map((res: Response) => res.json())
    }
}

Above gets injected to the component bellow.

import {Component} from '@angular/core';
import {CarService} from 'path/to/car.service';

@Component({
    selector: 'home',
    providers: [ CarService ],
    template: `
        <div>
            <button (click)="getCar()">Get Car</button>
            <h2>The car has {{ tiresCount }} tires.</h2>
        </div>
    `
})
export class Home {
    tiresCount: number;
    constructor(private carService: CarService) { }
    getCar() {
        this.carService.getCar()
            .subscribe(function(data){
                this.tiresCount = data.tires.count;
                console.log(this.tiresCount); // 4
        };
        console.log(this.tiresCount); // undefined
    }
}

What I am trying to do is to display the number of tires in the view of the Home component when the button is clicked. The problem is that, when I console.log(this.tiresCount) inside the .subscribe parentheses, it logs 4 but logs undefined outside of it. This means that the local property tiresCount did not get the new value so that it won't display anything in the view.

I suspect I am missing something obvious. Or perhaps, the understanding of Observables and/or RxJS is needed here as I am new to them.

2
  • 2
    Observables in this case function in a nearly identical manner to promises...asynchronous by nature. As a result, you're expecting that your outside console.log will be defined when it runs, but it won't. It'll fire off the call to getCar and THEN hit the outside console.log BEFORE the async response is returned. Commented May 8, 2016 at 4:52
  • That makes sense, but I am also trying to understand why the local property tiresCount does not receive the new value after the response is returned. Commented May 8, 2016 at 4:59

1 Answer 1

5

Use lambda expression "aka, arrow function" instead of function(){..} in your subscribe method. When using function(){...}, this inside it will refer to the function itself instead of the Home component class.

getCar() {
    this.carService.getCar()
            .subscribe(data => {
                this.tiresCount = data.tires.count;
                console.log(this.tiresCount); // 4
    });
    console.log(this.tiresCount); // undefined
}
someWhereElse(){
    console.log(this.tiresCount); // 4 , only after getCar().subscribe() resolves 
}
Sign up to request clarification or add additional context in comments.

2 Comments

This worked. What this refers to was crucial. Also, I did not know the syntax of the lambda expression requires { } around the statements. I tried without them first and it did not work, so I used function(){..} instead, which was not a good idea. Thanks!
you are welcome @jayscript, the lambda expression does not require {...} unless the body is multiline. Otherwise you can just .subscribe(data=>this.tiresCount=data.tires.count)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.