5
votes

I'm working on an Angular 7 project, and I'm facing a weird problem that took me some considerable time to identify, but I don't know why this is happening and I hope you guys can help me. I created a service using angular-cli, and then I implemented it as follows:


    import {Injectable} from '@angular/core';
    import {HttpClient} from "@angular/common/http";
    import {forkJoin, Observable} from "rxjs";
    import {map} from "rxjs/operators";

    @Injectable({
      providedIn: 'root'
    })
    export class SampleService {

      constructor(private http: HttpClient) {
      }

      save(sample: Sample): Observable {
        return this.http.post("http://localhost:3000/samples", sample).pipe(map(this.parser));
      }

      saveAll(samples: Sample[]): Observable {
        return forkJoin(samples.map(this.save))
      }

      private parser = (value): Sample => new Sample(value.name);
    }

    export class Sample {
      name: string;

      constructor(name: string) {
        this.name = name;
      }
    }

I put a breakpoint on each method. When I run it I get the following:

First breakpoint stop

As you can see, everything seems ok in the first breakpoint, so let's go to the next.

Second breakpoint stop

Now everything is undefined, and I get the following error in the console:


    ERROR TypeError: Cannot read property 'http' of undefined

If I change this line:


    forkJoin(samples.map(this.save))

to


    forkJoin(samples.map(sample => this.save(sample)))

When I rerun the code. I get:

Third breakpoint stop

And now everything seems to be ok, and the code works just fine. As a java developer, in a similar situation, the first way is comparable to a method reference and it would work just fine, why in TypeScript it doesn't?

1
this is how javascript works. If you want to keep the first option then write it as instance function github.com/Microsoft/TypeScript/wiki/…yurzui
Its related to the context of object. In first case context will change however in second option context will always be the same. Refer- ryanmorr.com/understanding-scope-and-context-in-javascriptSunil Singh
return forkJoin(samples.map(sample => this.save(sample)));JB Nizet

1 Answers

2
votes

this is contextual. Every function defined using function definition gets its own this. Arrow function definition works differently in that, it binds the parent context to the function body, making this refer to the parent this. It is similar to defining a function and binding it explicitly like:

function(doc){
//function body
}).bind(this)