Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

242
Views
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 answers
Answer question

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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!