IIIb. Angular 4 Openwebinars

De wikijoan
Salta a la navegació Salta a la cerca

Pipes

Componentes creados por angular que transforman datos (y podemos crear el nuestro propio).

  • date (formateo de fechas)
  • json (llamar a JSON.strinfigy(valor))
  • slice (substring)
  • uppercase, lowercase & titlecase
  • number (formateo de decimales)
  • percent (formateo de porcentajes)
  • currency (formateo de monedas)

Servicios

Una clase con lógica de negocio, para encapsular código

Habitualmente usa el módulo http (para hacer llamadas http) y la librería Rx.

Podemos crear un objeto con Angular CLI con:

$ ng g s Talks
@Injectable()
export class TalksService {

 constructor() { }

}

Es una clase sin código específico de angular salvo la anotación @Injectable para decir que puede tener dependencias con otros servicios.

Para usar el servicio tenemos que hacer 2 cosas:

  • Tenemos que inyectarlo en el constructor de la clase que quiere usarlo. La inyección más sencilla se hace en base al tipo:
  constructor(talksService: TalksService) {

  }

Angular busca una fábrica de ese objecto, un provider, en base al tipo del objecto. El tipo tiene que ser explícito.

  • Tenemos que proveer ese objecto, decirle a angular cómo construirlo. La forma más sencilla es especificando en un módulo (cómo el raíz), en la propiedad del módulo providers, éste código:
    providers: [TalkService]

Características básicas de la inyección

Los servicios inyectados de esa forma son singletons globales.

Si lo definimos en la propiedad providers de un módulo, es un singleton global compartido por todos los componentes que lo inyecten. Si, en cambio, lo definimos en la propiedad providers de cada componente se inyectará una instancia por cada componente que lo provea y hacia abajo (todos los hijos compartirán la misma instancia).

Inyección de dependencias

¿Por qué es útil?

  • Cuando escribimos new something() añadimos acoplamiento
  • El acoplamiento es malo, impide cambiar el código porque nos obliga a modificar muchos ficheros y muchas líneas
  • El acoplamiento de construcción nos impide cambiar la implementación, usar una clase hija por ejemplo.

¿Qué es IoC o DI?

Inversión de control (IoC) es una forma de evitar el problema del acoplamiento al usar constructores. La idea es invertir el control de la creación. En vez de ser el método que va usar esa instancia, será otro método/clase…

Inyección de dependencias (DI) es una forma de implementar inversión de control, inyectando las dependencias. Una librería/framework/contenedor será el encargado de construir y pasar las dependencias a quién quiera usarlas.

Nos permite que los componentes sepan menos cosas (ya no sabrían que parámetros se necesitan para construir, por ejemplo). Mejora la encapsulación.

Al ser componentes más pequeños que saben menos cosas, tienen menos razones para cambiar y los cambios están más aislados.

Todo esto me permite más flexibilidad porque, al no tener instanciación, puedo proveer implementaciones de esa instancia que sean diferentes a lo que pensaba el programador que escribió el código, con tal de que usé el mismo contrato.

Y me permite testear mejor, porque puedo pasar instancias de prueba que no llaman a servicios pesados.

¿Cómo usa DI Angular?

Hace inyección de dependencias en base al constructor y dependiendo del tipo del objecto.

Para inyectar algo tengo que:

  • Ver si lo que quiero inyectar tiene a su vez dependencias inyectadas. Si es así tendrá que estar anotado con @Inyectable o @Component…
  • Y dónde quiera usar esa dependencia hacer lo siguiente. Lo importante es no dejarnos la declaración del tipo.
  constructor(talksService: TalksService) {

  }
  • Tenemos que proveer ese objecto, decirle a angular cómo construirlo. La forma más sencilla es específicando en un módulo (cómo el raíz), en la propiedad del módulo providers, éste código:
  providers: [TalkService]

¿Qué siginifica esa sintaxis de providers?

Es una forma abreviada de:

{provide: TalksService, useClass: TalksService}

Cuando encuentres en un constructor un tipo, mira a ver si puedes inyectarlo y para ello mira en todos los providers definidos.

En el caso sencillo, crea un singleton de esa clase.

Pero se puede modificar pasando, al array de providers, definiciones como la siguiente:

{provide: DataService, useFactory: () => {//CODIGO}}

En este ejemplo podemos ejecutar código condicional para inyectar una instancia u otra dependiendo de una propiedad, estado de la build…

Otro ejemplo de inyección es:

{provide: 'defaultSearch',  useValue: 'http://www.google.es')

Y en el constructor que quiera usar ese valor :

    constructor(@Inject('apiUrl') url) {

    }

Que nos permite inyectar cualquier cosa (cadenas…) en base a un nombre (apiUrl en este caso).

HTTP

Módulo adicional para hacer http requests.

Generalmente usa RxJS (explicado más adelante).

Una forma de hacer una petición sencilla sería la siguiente:

constructor(public http: Http) { 
  this.http.get('http://data.agenda.wedeploy.io/talks')
  .do(x => console.log(x))
  .map(res => res.json())
  .subscribe(x => this.talks = x)
}

En este ejemplo estamos usando 3 cosas:

  • Inyección de dependencias del objeto http para hacer peticiones de red.
  • Uso de http para hacer una petición get y el parseo a json().
  • Un flujo de Rx aplicando transformaciones y una suscripción que explicaremos a continuación.

La librería de http estándar tiene métodos muy útiles cómo:

  • json() (para obtener el json de una response)
  • text() (para obtener el texto)
  • Headers() (para pasar cabeceras)

Otras librerías de http

En angular podemos hacer peticiones manuales, usar JSONP o el API estándar de ES2015, fetch.


creat per Joan Quintana Compte, març 2019