Reputation: 15
I am currently going through the Angular tutorial and came across the following code:
getHero(id: number): Promise<Hero> {
return this.getHeroes().then( heroes => heroes.find( hero => hero.id === id ));
}
Out of curiosity, I decided to rewrite the callback function using a normal function:
getHero(id: number): Promise<Hero> {
return this.getHeroes().then( heroes => heroes.find( this.findHero, id));
}
findHero(hero: Hero, index: number, array: Hero[]): boolean {
if(hero.id === this.id){
return true;
}else{
return false;
}
}
But this gives me the error Property 'id' does not exist on type 'HeroService'.
How may I refer to the id
parameter passed to my callback function?
Upvotes: 0
Views: 173
Reputation: 2531
The id
(number) property is defined as an argument of the function getHero
, thus, is not available in your function findHero
. You tried to use this.id
but the compiler is telling you that such a property does not exits in your class HeroService
, which is correct of course, as if you wanted to have that property as part of your service then you would have to do something like this in your getHero
method.
getHero(id: number, ...etc) {
this.id = id;
// etc.
}
However, that would bring you another problem: as your method getHeroes
seems to be async code (I can tell because it is returning a Promise
) this approach will cause you headaches with concurrency problems when your method getHero
is called twice (or more times) from different parts of the application. The first getHero
call will set this.id
to x
but in the meantime, while the async code is run, another call to getHero
will set it to y
, making that the callback findHero
run in response to the first call use an incorrect value for the id
(specifically, it will read y
as the value for this.id
).
So... long story short. You would probably want to read more about CLOSURES and why they are so important for JavaScript. Short answer to your question, use this:
getHero(id: number): Promise<Hero> {
return this.getHeroes().then( heroes => heroes.find(this.findHero.bind(this, id));
}
And define your callback findHero
as
findHero(idToFind: number, hero: Hero, index, array: Hero[]) {
return hero.id === idToFind;
}
The reason why you need this is that the this
is not passed automatically to the functions that you use as arguments for other functions (or methods, as in this case). So by using bind
you explicitly BIND the this
of such a function so that whenever you use this
in findHero
it points to the right object. The second argument of bind
is binding the id
you are looking for to every call of the function findHero
, so that whenever the function returned by bind
is called it happens two things:
this
is bound to HeroService
. Just one minor note... you are using TypeScript, so the this
argument in your bind
is pointless, as TypeScript automatically binds all methods in your class to the current instance, but you need it in this case because you also want to bind the second argument (the id
to find).
I hope it I helped.
Upvotes: 2