Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

243
Visualizações
Angular – loosing reference to `this` when passing function as parameter

I am building an Angular application, and I have two services, call them ServiceA and ServiceB. ServiceB has two methods that ServiceA uses in the same way, something like this:

@Injectable({
    providedIn: 'root'
})
export class ServiceA {
    constructor(private _b: ServiceB) {}

    doFoo(input: Whatever): void {
        this._b.foo(input)
            .pipe(...);
            .subscribe(...);
    }

    doBar(input: Whatever): void {
        this._b.bar(input)
            .pipe(...); // exact same pipe as above
            .subscribe(...); // exact same subscribe as above
    }
}

Since I have duplicate logic, I tried to do this in ServiceA:

performFooBarAction(input: Whatever, fooBarFn: (input: Whatever) => Observable<void>): void {
    fooBarFn(input).pipe(...).subscribe(...);
}

And call it from both methods like this:

doFoo(input: Whatever): void {
    this.performFooBarAction(input. this._b.foo);
}

But, if I do it like that I get an error:

Cannot read properties of undefined

So, I tried to add console.log(this) to serviceB.foo(), and – lo and behold – this is undefined when I pass the function as an argument. It worked before my little refactor.

Any idea if this is unavoidable, or is it me who's doing it wrong?

about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

You can also try this:

@Injectable({
    providedIn: 'root'
})
export class ServiceA {
    constructor(private _b: ServiceB) {}

    doFoo(input: Whatever): void {
        this._b.foo(input)
            .pipe(...);
            .subscribe(...);
    }

    doBar(input: Whatever): void {
        this._b.bar(input)
            .pipe(...); // exact same pipe as above
            .subscribe(...); // exact same subscribe as above
    }

    callMethodByName(input: Whatever, funcName: string) {
        this._b[funcName](input).pipe().subscribe();
    }

}

A working sample is attachted below:

class Testing {

logName(name) {
    console.log(`Name is ${name}`);
}

logAge(age) {
    console.log(`Age is ${age}`);
}

print(funcName, data) {
   this[funcName](data);
}
}

const tes = new Testing();
tes.print('logName', 'Apoorva Chikara');
tes.print('logAge', 29)

about 4 years ago · Juan Pablo Isaza Relatório

0

bind context when passing function as an argument:

 doFoo(input: Whatever): void {
        this.performFooBarAction(input. this._b.foo.bind(this._b));
    }
about 4 years ago · Juan Pablo Isaza Relatório

0

I managed to solve this by invoking the call method and passing it the reference to ServiceB as context, like so:

performFooBarAction(input: Whatever, fooBarFn: (input: Whatever) => Observable<void>): void {
    fooBarFn.call(this._b, input).pipe(...).subscribe(...);
}

But if someone can tell me if there is a better way, I'd be thankful.


[EDIT] - Another solution

Since I discovered I actually won't have the same parameter list for foo() and bar(), I came up with another way, which doesn't require context passing, and works in both cases - I simply passed the Observables that come from _b.foo() and _b.bar() like this:

handleFooBarAction(input$: Observable<void>): void {
  input$.pipe(...).subscribe(...);
}

Which I can now call like this:

doFoo(input: Whatever): void {
    this.handleFooBar(this._b.foo(input));
}

doBar(): void { // no params
    this.handleFooBar(this._b.bar()); // no params
}
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda