Comprender el contexto de inyección angular

May 02 2023
Angular introdujo la función inject() en versiones recientes, lo que nos permite obtener una referencia a un proveedor de manera funcional en lugar de usar el método Injector.get().

Angular introdujo la inject()función en versiones recientes, lo que nos permite obtener una referencia a un proveedor de manera funcional en lugar de usar el Injector.get()método. Sin embargo, si lo ha usado o una biblioteca que lo usa bajo el capó, es posible que haya encontrado el siguiente error:

inject() must be called from an injection context 
such as a constructor, a factory function, a field initializer, 
or a function used with `runInInjectionContext`.

Angular tiene dos variables globales que pueden contener un injectoren un momento determinado: una para an Injectory otra para NodeInjector. Aquí están los fragmentos de código para ambos:

let _currentInjector = undefined;

export function getCurrentInjector() {
  return _currentInjector;
}

export function setCurrentInjector(injector: Injector|undefined|null {
  const former = _currentInjector;
  _currentInjector = injector;
  return former;
}
let _injectImplementation

export function getInjectImplementation() {
  return _injectImplementation;
}

export function assertInInjectionContext(debugFn: Function): void {
  if (!getInjectImplementation() && !getCurrentInjector()) {
    throw new RuntimeError(
        RuntimeErrorCode.MISSING_INJECTION_CONTEXT,
        ngDevMode &&
            (debugFn.name +
             '() can only be used within an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`'));
  }
}

import {
  ElementRef,
  assertInInjectionContext,
  inject,
} from '@angular/core';

export function injectNativeElement<T extends Element>(): T {
  assertInInjectionContext(injectNativeElement);

  return inject(ElementRef).nativeElement;
}

  • En la factoryfunción especificada para un InjectionToken:
  • export const FOO = new InjectionToken('FOO', {
      factory() {
        const value = inject(SOME_PROVIDER);
        return ...
      },
    });
    

    
    @Component({
      providers: [
        {
          provide: FOO,
          useFactory() {
            const value = inject(SOME_PROVIDER);
            return ...
          },
        },
      ]
    })
    export class FooComponent {}
    

    @Component({})
    export class FooComponent {
      foo = inject(FOO);
    
      constructor(private ngZone: NgZone = inject(NgZone)) {
        const bar = inject(BAR);
      }
    }
    

  • Dentro de una función que se ejecuta usando la runInInjectionContextfunción:
  • import { runInInjectionContext } from '@angular/core';
    
    export class FooComponent {
      ngOnInit() {
        runInInjectionContext(this.injector, () => {
          console.log(
            'I can access the NodeInjector using inject()',
            inject(ElementRef)
          );
        })
    }
    

¡ Sígueme en Medium o Twitter para leer más sobre Angular y JS!