Comprendre le contexte d'injection angulaire

May 02 2023
Angular a introduit la fonction inject() dans les versions récentes, ce qui nous permet d'obtenir une référence à un fournisseur de manière fonctionnelle plutôt que d'utiliser la méthode Injector.get().

Angular a introduit la inject()fonction dans les versions récentes, ce qui nous permet d'obtenir une référence à un fournisseur de manière fonctionnelle plutôt que d'utiliser la Injector.get()méthode. Cependant, si vous l'avez utilisé ou une bibliothèque qui l'utilise sous le capot, vous avez peut-être rencontré l'erreur suivante :

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 a deux variables globales qui peuvent contenir an injectorà un certain moment : une pour an Injectoret une pour NodeInjector. Voici les extraits de code pour les deux :

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;
}

  • Dans la factoryfonction spécifiée pour 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);
      }
    }
    

  • À l'intérieur d'une fonction exécutée à l'aide de la runInInjectionContextfonction :
  • import { runInInjectionContext } from '@angular/core';
    
    export class FooComponent {
      ngOnInit() {
        runInInjectionContext(this.injector, () => {
          console.log(
            'I can access the NodeInjector using inject()',
            inject(ElementRef)
          );
        })
    }
    

Suivez-moi sur Medium ou Twitter pour en savoir plus sur Angular et JS !