Skip to content

Qu'est ce que factory function (useFactory) ?

Les factory functions ont plusieurs avantages :

  • Elles permettent de configurer un objet injectable de manière flexible et personnalisée. Par exemple, vous pouvez utiliser une factory function pour créer une instance d'une classe en lui passant des paramètres de configuration, ou pour retourner une valeur prédéfinie en fonction de certains critères.

  • Elles permettent de découpler la création d'un objet injectable de son utilisation. Cela signifie que vous pouvez changer la manière dont un objet injectable est créé sans avoir à modifier son code utilisateur. Cela peut être utile lorsque vous souhaitez fournir différentes versions d'un objet injectable dans différentes situations (par exemple, en fonction de l'environnement d'exécution ou de la configuration de l'application).

Exemple

Imaginons que vous avez un service qui permet de récupérer des données d'un serveur web. Vous souhaitez pouvoir configurer ce service de manière à ce qu'il utilise une URL différente selon l'environnement d'exécution (développement, production, etc.). Voici comment vous pouvez utiliser une factory function pour cela :

ts
import { Injectable } from '@angular/core';

@Injectable()
export class DataService {
  constructor(private baseUrl: string) { }

  getData() {
    // Récupère les données à partir de l'URL fournie dans le constructeur
  }
}

export function dataServiceFactory(environment: string) {
  let baseUrl: string;
  if (environment === 'production') {
    baseUrl = 'https://www.example.com/api';
  } else {
    baseUrl = 'http://localhost:3000/api';
  }
  return new DataService(baseUrl);
}
import { Injectable } from '@angular/core';

@Injectable()
export class DataService {
  constructor(private baseUrl: string) { }

  getData() {
    // Récupère les données à partir de l'URL fournie dans le constructeur
  }
}

export function dataServiceFactory(environment: string) {
  let baseUrl: string;
  if (environment === 'production') {
    baseUrl = 'https://www.example.com/api';
  } else {
    baseUrl = 'http://localhost:3000/api';
  }
  return new DataService(baseUrl);
}

Ensuite, vous pouvez utiliser cette factory function dans un provider comme suit :

ts
import { NgModule } from '@angular/core';
import { DataService, dataServiceFactory } from './data.service';

@NgModule({
  providers: [
    {
      provide: DataService,
      useFactory: dataServiceFactory,
      deps: ['ENVIRONMENT']
    }
  ]
})
export class MyModule { }
import { NgModule } from '@angular/core';
import { DataService, dataServiceFactory } from './data.service';

@NgModule({
  providers: [
    {
      provide: DataService,
      useFactory: dataServiceFactory,
      deps: ['ENVIRONMENT']
    }
  ]
})
export class MyModule { }

Dans ce cas, la factory function dataServiceFactory sera appelée avec l'environnement courant (qui est fourni par une valeur d'environnement externe) et retournera une instance de DataService avec l'URL appropriée.

Qu'est ce qu'est deps ?

En Angular, la propriété deps d'un provider permet de spécifier une liste de dépendances à injecter dans la factory function associée. Ces dépendances sont injectées dans l'ordre dans lequel elles sont déclarées dans la liste deps.

Voici un exemple de provider avec des dépendances injectées dans la factory function :

ts
import { NgModule } from '@angular/core';
import { DataService, dataServiceFactory } from './data.service';

@NgModule({
  providers: [
    {
      provide: DataService,
      useFactory: dataServiceFactory,
      deps: [HttpClient, 'ENVIRONMENT']
    }
  ]
})
export class MyModule { }
import { NgModule } from '@angular/core';
import { DataService, dataServiceFactory } from './data.service';

@NgModule({
  providers: [
    {
      provide: DataService,
      useFactory: dataServiceFactory,
      deps: [HttpClient, 'ENVIRONMENT']
    }
  ]
})
export class MyModule { }

Dans cet exemple, la factory function dataServiceFactory sera appelée avec deux arguments : une instance d'HttpClient et une chaîne qui représente l'environnement courant. Ces dépendances sont injectées grâce aux mécanismes de l'injection de dépendances d'Angular.

La propriété deps est facultative. Si elle n'est pas définie, aucune dépendance ne sera injectée dans la factory function. Si vous avez besoin d'injecter des dépendances dans votre factory function, vous devez déclarer la liste de dépendances dans la propriété deps du provider correspondant.