Estoy creando una aplicación Angular y tengo dos servicios, ServiceA y ServiceB . ServiceB tiene dos métodos que ServiceA usa de la misma manera, algo como esto:
@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 } } Como tengo una lógica duplicada, traté de hacer esto en ServiceA :
performFooBarAction(input: Whatever, fooBarFn: (input: Whatever) => Observable<void>): void { fooBarFn(input).pipe(...).subscribe(...); }Y llámalo desde ambos métodos así:
doFoo(input: Whatever): void { this.performFooBarAction(input. this._b.foo); }Pero, si lo hago así, me sale un error:
No se pueden leer las propiedades de undefined
Por lo tanto, traté de agregar console.log(this) a serviceB.foo() y, he aquí, this no está undefined cuando paso la función como argumento. Funcionó antes de mi pequeño refactor.
¿Alguna idea de si esto es inevitable, o soy yo quien lo está haciendo mal?
También puedes probar esto:
@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 continuación se adjunta una muestra de trabajo:
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)enlazar contexto al pasar la función como argumento:
doFoo(input: Whatever): void { this.performFooBarAction(input. this._b.foo.bind(this._b)); }Logré resolver esto invocando el método de call y pasándole la referencia a ServiceB como contexto, así:
performFooBarAction(input: Whatever, fooBarFn: (input: Whatever) => Observable<void>): void { fooBarFn.call(this._b, input).pipe(...).subscribe(...); }Pero si alguien me puede decir si hay una mejor manera, estaría agradecido.
[EDITAR] - Otra solución
Como descubrí que en realidad no tendré la misma lista de parámetros para foo() y bar() , se me ocurrió otra forma, que no requiere pasar contexto y funciona en ambos casos: simplemente pasé el Observable s que vienen de _b.foo() y _b.bar() así:
handleFooBarAction(input$: Observable<void>): void { input$.pipe(...).subscribe(...); }Que ahora puedo llamar así:
doFoo(input: Whatever): void { this.handleFooBar(this._b.foo(input)); } doBar(): void { // no params this.handleFooBar(this._b.bar()); // no params }