Inyección de dependencias

Logo de typescript

Una de las ventajas que tiene Angular respecto a otros frameworks es la posibilidad de usar el patrón de diseño de inyección de dependencias. Este patrón sirve para proveer, suministrar, a las clases con las dependencias que se necesita.

Esto permite que el código se pueda testear mejor ya que puedes pasar dependencias mockeadas o otros tipos de dependencias desde los tests.

Imagina que inicializamos las dependencias de una clase de la manera tradiccional:

public Example() {
  object_test = Factory.getObject();
}

A la hora de testear esta clase es mucho más complicado porque si quieres comprobar la llamada a Factory (o quieres interceptarla no puedes).

Para ello lo que se hace es inicializar la dependencia directamente desde el constructor de Angular, de esta forma lo que conseguimos es que al testear la aplicación, podamos crear el objeto Factory desde fuera:

constructor(Factory factory) {
  object_test = Factory.getObject();
}

Pero con esto no basta, para que Angular pueda inyectar esta dependencia tienes que hacer que Factory sea un objeto inyectable, para ello, dentro del fichero de Factory tienes que usar la anotación de @Injectable():

// factory.ts

import { Injectable } from "@angular/core";

@Injectable({
  providedIn: "root",
})
export class Factory {
  constructor() {}
}

En este caso, se crea la anotación Injectable encima de la declaración de la clase. providedIn es un atributo especial de las anotaciones inyectables.

providedIn: 'root' significa que Angular creará una sola instancia de esta clase para poder inyectarla de forma global en los componentes que la necesite. Esto permite ahorrar recursos y optimizar las webs de Angular al no tener que crear una instancia por dependencia aunque sea de la misma clase.