Material‎ > ‎Software‎ > ‎Angular 1.x con ES6‎ > ‎

AngularJS - Services - ES6

Objetivo
Los servicios permiten reutilizar funcionalidades comunes en varios contextos, como los controllers. Algunos ejemplos son:
  • obtener información de un origen de datos / actualizar dicho origen
  • guardar la información del cliente en un cache local para luego sincronizarse con repositorios remotos
  • proveer lógica de negocio en el cliente (si seguimos una estrategia de programación funcional) o bien delegar en objetos de dominio (si nuestra estrategia se asocia más a la programación con objetos)
Los services de AngularJS
  • son singleton
  • y se crean en el momento que algún otro componente de Angular lo define como dependencia, lo que se conoce como inyección de dependencias. Los componentes que pueden utilizarlos son controllers, directivas, filtros u otros servicios)

Servicios builtin

AngularJS viene con varios services incorporados:

SERVICEDESCRIPTION
$httpAllows promise-based access to HTTP requests (API Reference: ng.$http)
$resourceProvides a higher-level abstraction for accessing REST-style services (API Reference: ng.$resource)
$documentIs a jQuery (lite)-wrapped reference to window.document (API Reference: ng.$document)
$windowIs a jQuery (lite)-wrapped reference to window (API Reference: ng.$window)
$timeoutThis is a wrapped version of window.setTimeout. In tests, you can use $timeout.flush() to synchronously execute all scheduled timeouts. (API Reference: ng.$timeout)
$parseParses Angular expressions (for example, for binding withng-model or similar) and provides accessor functions (API Reference: ng.$parse)
$cacheFactoryUsually used by other services whenever they need a scoped cache of elementes (API Reference: ng.$cacheFactory)
$filterProvides programmatic access to a filter function (API Reference: ng.$filter)
Todos comienzan con el prefijo $.

Definición de un servicio propio

En el presente ejemplo veremos el clásico conversor utilizando dos controllers que comparten información a partir de un objeto de dominio conversor definido en el service. Utilizamos el objeto de dominio Conversor con propiedades millas y kilómetros. Luego, definimos 
  1. un objeto service que en realidad es nuestro objeto de dominio Conversor, compartido por
  2. dos controllers, uno que delega al service y otro que es directamente el mismo service

class ConversorController {
constructor(conversorService) {
this.conversorService = conversorService
}

convertir() {
console.log("convertir del controller")
this.conversorService.convertir()
}
}

/** Definición de controllers y services */
angular.module('conversorApp', [])
.service('conversorService', Conversor)
.controller('conversorCtrl', ConversorController)
.controller('conversor2Ctrl', (conversorService) => {
return conversorService
})

Como resultado, 
  • cuando ingresamos las millas, el binding se da del primer controller al service, actualizando la propiedad millas
  • cuando se presiona el botón convertir, el binding del evento on-click produce la activación del mensaje convertir() desde el primer controller al service que es el objeto de dominio. Esto produce el cambio en la propiedad kilómetros...
  • ...que es escuchado por ambos controllers, por lo que se ve reflejado en la pantalla
De esta manera dos controllers pueden manejar su propia lógica independiente pero compartiendo información común.

<body ng-controller="conversorCtrl as conversorCtrl">
    <div class="container">
        <div class="page-header">
            <h1>Conversor <small>AngularJS</small></h1>
        </div>

        <div class="well well-lg">
            <h2>Convertir</h2>
            <div>
                <form name="convertirForm" role="form">
                    <fieldset>
                        <div class="form-group">
                            <label for="titulo">Millas</label>
                            <input
                                name="millas"
                                class="form-control"
                                ng-model="conversorCtrl.conversorService.millas"
                                required="true"
                                ng-pattern="/^[0-9]+$/"
                                placeholder="Ingrese la cantidad de millas a convertir"
                                autofocus="autofocus">
                        </div>
                        <div class="form-group" ng-controller="conversor2Ctrl as conversor2Ctrl">
                            <label for="kilometros">Kilometros</label>
                            <p class="lead"
                                data-ng-show="convertirForm.millas.$valid">{{conversor2Ctrl.kilometros}}</p>
                        </div>
                        <button type="submit" class="btn btn-primary"
                            data-ng-click="conversorCtrl.convertir()">Convertir</button>

Service vs. Factory

Para definir un service tenemos tres opciones:
  • hacerlo con el método service, que trabaja con un objeto definido como una función
  • hacerlo con el método factory, que trabaja con un objeto definido como un mapa de propiedades
  • hacerlo con el método provider, que se suele utilizar para mockear al service en el testeo unitario
Veamos el siguiente ejemplo extraído de Stack Overflow.

Otros ejemplos
Puede verse la explicación sobre servicios REST utilizando el servicio built-in $http para ver cómo interactúa un servicio AngularJS contra un origen de datos remoto.

Links relacionados

Comments