Que fait angular-di ?
Implémenter l'injection de dépendances dans Angular v20+ en utilisant inject(), les tokens d'injection et la configuration des providers. Utilisé pour l'architecture de services, la fourniture de dépendances à différents niveaux, la création de tokens injectables et la gestion des services singleton ou scopés. Se déclenche lors de la création de services, de la configuration de providers, de l'utilisation de tokens d'injection ou de la compréhension de la hiérarchie des injecteurs.
Vue d'ensemble
Cette compétence couvre les aspects essentiels du système d'injection de dépendances d'Angular dans les versions 20 et ultérieures. L'API DI moderne repose principalement sur la fonction inject() (introduite comme stable dans Angular 14) et les tokens d'injection typés.
Concepts clés
inject(): La fonction principale pour obtenir des dépendances. Elle remplace l'injection par constructeur dans la plupart des cas et est disponible dans tous les contextes d'injection (constructeurs de services, factories, guards, resolvers).InjectionToken<T>: Crée un token typé pour les dépendances qui ne sont pas des classes (par exemple, des configurations, des chaînes, des objets).providedIn: Définit la visibilité et le cycle de vie d'un service. Les options courantes incluent'root'(singleton applicatif), le nom d'unNgModulespécifique, ou'platform'(pour les environnements multi-applications).- Providers : Configurés via les décorateurs
@Injectable, les tableauxprovidersdesNgModule, ou lesprovidersdes@Component/@Directive.
Utilisation courante
Créer un service avec providedIn: 'root'
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class LoggerService {
log(message: string) {
console.log(message);
}
}
Utiliser inject() au lieu de l'injection par constructeur
import { inject, Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { LoggerService } from './logger.service';
@Injectable()
export class DataService {
private http = inject(HttpClient);
private logger = inject(LoggerService);
fetchData() {
this.logger.log('Récupération des données...');
return this.http.get('/api/data');
}
}
Créer et utiliser un InjectionToken
import { InjectionToken, inject, Injectable } from '@angular/core';
export interface AppConfig {
apiUrl: string;
timeout: number;
}
export const APP_CONFIG = new InjectionToken<AppConfig>('app.config');
@Injectable()
export class ConfigService {
private config = inject(APP_CONFIG);
getApiUrl(): string {
return this.config.apiUrl;
}
}
Fournir le token dans un module ou un composant :
import { NgModule } from '@angular/core';
import { APP_CONFIG } from './app-config.token';
@NgModule({
providers: [
{
provide: APP_CONFIG,
useValue: {
apiUrl: 'https://api.example.com',
timeout: 5000
}
}
]
})
export class AppModule { }
Provider avec useFactory
import { inject, InjectionToken } from '@angular/core';
import { HttpClient } from '@angular/common/http';
export interface CacheService {
get(key: string): Promise<any>;
set(key: string, value: any): void;
}
export const CACHE_SERVICE = new InjectionToken<CacheService>('cache.service', {
factory: () => {
const http = inject(HttpClient);
return {
get: async (key: string) => {
return http.get(`/cache/${key}`).toPromise();
},
set: (key: string, value: any) => {
// Logique de cache local
localStorage.setItem(key, JSON.stringify(value));
}
};
}
});
Hiérarchie des injecteurs
Les injecteurs Angular suivent une hiérarchie :
- Injecteur de plateforme : Singleton pour toute l'application (rarement utilisé).
- Injecteur racine (ModuleInjector) : Fourni via
providedIn: 'root'ouNgModule.providers. - Injecteur d'élément (ElementInjector) : Associé à chaque composant/directive via leurs
providers. - Injecteur nulle (NullInjector) : L'injecteur le plus haut ; lève une erreur si aucune dépendance n'est trouvée.
Un service défini dans providers d'un composant est unique pour ce composant et ses enfants. Un service défini avec providedIn: 'root' est un singleton partagé dans toute l'application.
Meilleures pratiques
- Préférer
inject()à l'injection par constructeur pour une meilleure testabilité et flexibilité, surtout dans les composants et directives. - Utiliser
InjectionTokenpour les dépendances non-class avec des valeurs de configuration type-safe. - Éviter les singletons globaux abusifs : utiliser
providedInau niveau des composants pour des données limitées à un contexte (par exemple, un état local). - Organiser les providers par fonctionnalité dans des
NgModuledédiés ou desstandalone components. - Documenter les tokens d'injection avec des noms descriptifs pour faciliter le débogage.