Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

unidades:03_servicios:09_provider [2014/07/30 17:04]
admin
unidades:03_servicios:09_provider [2014/09/22 19:02] (actual)
admin [3.9 provider]
Línea 2: Línea 2:
 Por fin llegamos al ''​provider''​ el último de los tipos de servicios en AngularJS y con el que espero que se entiendan por fin las diferencias entre todos ellos. Por fin llegamos al ''​provider''​ el último de los tipos de servicios en AngularJS y con el que espero que se entiendan por fin las diferencias entre todos ellos.
  
-Un ''​provider''​ es como un ''​factory'' ​solo que permite que se configure antes de crear el valor del servicio. En el tema anterior ​hemos visto el ejemplo del servicio de ''​hash''​ que se configuraba a través de un ''​value''​ llamado ''​algoritmo''​. Aunque el ejemplo ​ha funcionado, la verdad es que es un poco chapucero ya que aparentemente no hay relación entre ''​algoritmo''​ y ''​hash''​ . La relación entre ambos queda poco orientada al objeto. El ''​provider''​ viene en nuestra ayuda creando un objeto previo que permite configurar el factory antes de que cree el valor del servicio. Este nuevo objeto se llama **Provider** y en un bloque ''​config''​ podremos acceder a él para poder configurar nuestro servicio.+Un ''​provider''​ es como un ''​factory'' ​pero permite que se configure antes de crear el valor del servicio. En el tema anterior ​vimos el ejemplo del servicio de ''​hash''​ que se configuraba a través de un ''​value''​ llamado ''​algoritmo''​. Aunque el ejemplo ​ ​funciona, la verdad es que es un poco chapucero ya que aparentemente no hay relación entre ''​algoritmo''​ y ''​hash''​ . La relación entre ambos queda poco orientada al objeto. El ''​provider''​ viene en nuestra ayuda creando un objeto previo que permite configurar el factory antes de que cree el valor del servicio. Este nuevo objeto se llama **Provider** y en un bloque ''​config''​ podremos acceder a él para poder configurar nuestro servicio.
  
-Como siempre hacemos ​veamos ​un ejemplo: +<note tip> 
-<sxh js;>+Un provider está compuesto de 2 partes: 
 +  * El provider que es una clase JavaScript de la que se crea un único objeto , el cual permite llamar en un bloque config antes de que se llame al factory-provider y asi poder configurar el factory-provider. 
 +  * El factory-provider,​ el cual crea el valor del servicio. Es prácticamente como la función factory del tema anterior y la llamamos factory-provider 
 +</​note>​ 
 + 
 + 
 +Como siempre hacemos, vamos a ver un ejemplo: 
 +<sxh js;highlight: [1,​2,​4,​8,​35];>
 function HashProvider() { function HashProvider() {
   var _algoritmo="";​   var _algoritmo="";​
Línea 43: Línea 50:
 </​sxh>​ </​sxh>​
  
-Tenemos una nueva clase llamada ​''​HashProvider'' ​con lo siguiente: +  * Línea 1: Definimos la clase ''​HashProvider''​. Posteriormente AngularJS creará una instancia de esta clase. 
-  * ''​_algoritmo''​: Es una propiedad privada que contendrá el algoritmo a usar. +  * Línea 2: Se define la propiedad privada ​''​algoritmo'' ​la cual contendrá el algoritmo a usar. 
-  * ''​setAlgoritmo''​: Método público que nos permite establecer el algoritmo a usar antes de crear la función de hash. +  * Línea 4: Método público que nos permite establecer el algoritmo a usar antes de crear la función de hash. 
-  * ''​$get''​: Método público que es realmente el factory que creará el valor ser servicio.+  * Linea 8: Método público que es realmente el factory que creará el valor del servicio.En toda clase Provider es obligatorio que exista este método público llamado ''​$get''​. Es una obligación que impone AngularJS para que él sepa cuál es el método factory. Podemos ver que este método es exactamente igual al del tema anterior de [[unidades:​03_servicios:​08_factory|factory]] excepto que ahora usa la propiedad privada ''​_algoritmo''​ en vez de llamar al servicio ''​algoritmo''​. Éste es el método que en el tema [[unidades:​03_servicios:​04_tiposservicios]] llamábamos "​factory-provider"​. 
 +  * Línea 35: Definimos el ''​provider''​ con el nombre ''​hash''​ y le pasamos como argumento el nombre de la clase ''​HashProvider''​.
  
-En toda clase que quiera ser un provider es obligatorio que exista ​el método público ​llamado ​''​$get''​. ​Es una obligación ​que impone AngularJS para que él sepa cual es el método factory.+Resumiendo, hemos creado una clase JavaScript llamada ''​HashProvider''​ con distintas propiedades y métodos ((en nuestro ejemplo sólo está la propiedad privada ''​_algoritmo''​ y el método público ​''​setAlgoritmo''​ )) que permitirán configurar el factory-provider. El factory-provider es la función ​''​$get'' ​del providerPor lo tanto dicha función hará uso de las propiedades ​que se han definido en la clase ((en nuestro ejemplo hace uso de la propiedad ''​algoritmo''​)).
  
-Si nos fijamos en el método ''​$get''​ veremos que es exactamente igual al del tema anterior de [[unidades:​03_servicios:​08_factory|factory]] excepto ​que ahora usa la propiedad privada ''​_algoritmo''​ en vez de llamar al servicio ''​algoritmo''​.+===== Configurando ​el provider ===== 
 +Ya tenemos definido el provider pero ahora es necesario poder configurarlo para establecer cuál es el algoritmo a usar. Los [[unidades:​03_servicios:​04_tiposservicios&#​bloque_config|bloques config]] son los únicos ​que permiten configurar el provider. 
 + 
 +En el bloque config será necesario inyectar el provider , **no el factory-provider** para poder configurarlo.
  
-<note tip> 
-No vamos a poner un ejemplo aquí pero a la función de ''​$get''​ se le pueden seguir inyectando servicios quedando de la siguiente forma: 
 <sxh js> <sxh js>
-this.$get=['​serv1','​serv2'​,function(serv1,serv2) { +app.config(["​hashProvider"​,function(hashProvider) { 
-}];+  hashProvider.setAlgoritmo("​SHA-1"​);​ 
 +}]);
 </​sxh>​ </​sxh>​
 +  * Línea 1: Inyectamos el provider en la función de config. Nótese que AngularJS nos obliga en este caso a llamar al provider "​hashProvider"​ . Es decir que al nombre de nuestro servicio se añade la palabra "​Provider"​ y de esa forma le estamos diciendo que queremos el objeto provider para configurarlo y no el objeto final del servicio.
 +  * Línea 2: Ahora llamamos al método público del provider llamado ''​setAlgoritmo''​ para configurar el algoritmo.
 +
 +<note important>​
 +Recuerda que al inyectar el provider en un bloque config hay que incluir en el nombre el sufijo "​Provider"​.
 +
 +Por ejemplo si el servicio se llama "​login"​ ,al inyectarlo en un bloque config habrá que poner "​loginProvider"​
 +
 +</​note>​
 +
 +Una vez configurado el provider en el bloque config ya podremos inyectar el servicio donde queramos , en un controlador,​ en otro servicio, en un bloque run, etc.
 +
 +Volvamos ahora a repasar la diferencia entre los bloques config y los bloques run. Un bloque config sólo existe para poder configurar un provider y ninguno de los servicios está aún creado ((A excepción de ''​constant''​)). ​
 +
 +Mientras que en un bloque run todos los servicios ya está configurados y se pueden usar. Por ello el bloque run es más parecido a un método ''​Main''​ mientras que el bloque config es más parecido a un trozo de código de preinicialización de la aplicación.
 +
 +
 +
 +===== Inyectando dependencias =====
 +Ya hemos dicho que un provider está definido por 2 funciones:
 +  * La función constructora de la clase que permite la configuración,​ que llamamos provider
 +  * La función factory que crea el valor del servicio, que llamamos factory-provider.
 +
 +AngularJS nos permite en ambas funciones que podamos inyectar dependencias aunque en cada uno de ellos de tipos distintos. Veamos qué podemos inyectar en cada uno de ellos:
 +  * provider: Podemos inyectar sólo ''​constant''​ y otros providers pero definidos en otros módulos.
 +  * factory-provider:​ Podemos inyectar ''​constant'',​ ''​value'',​ ''​service'',​ ''​factory''​ y ''​factory-provider''​
 +
 +Veamos ahora un pequeño ejemplo de ello:
 +<sxh js;​highlight:​ [6,7];>
 +app.constant("​provincia","​Madrid"​);​
 +app.factory("​municipio",​function() {
 +  return "​Mostoles";​
 +});
 +
 +app.provider("​direccion",​['​provincia',​function(provincia) {
 +  this.$get=['​municipio',​function(municipio) {
 +    return provincia+","​+municipio;​
 +  }]
 +}]);
 +</​sxh>​
 +  * Línea 6: Definimos un provider llamado "​direccion"​ e inyectamos la constante ''​provincia''​.
 +  * Línea 7: En el factory-provider inyectamos el factory ''​municipio''​
 +
 +El ejemplo no tiene mucho sentido pero se ha puesto simplemente para ver que se pueden inyectar dependencias en ambas funciones.
 +
 +Otra cosa interesante de este ejemplo es que en vez de crear la función del Provider aparte , se ha definido como una función anónima de JavaScript. Son cosas que permite el propio lenguaje y no tienen nada que ver con AngularJS.
 +
 +===== Mejorando la configuración =====
 +Aún nos queda un pequeño cambio por hacer para mejorar la arquitectura del ejemplo.Al configurar el provider hemos puesto directamente en el bloque config el algoritmo a usar:
 +
 +<sxh js>
 +app.config(["​hashProvider",​function(hashProvider) {
 +  hashProvider.setAlgoritmo("​SHA-1"​);​
 +}]);
 +</​sxh>​
 +  * Línea 2: Tenemos el texto "​SHA-1"​ //a piñon//.
 +
 +Como todos sabemos no es buena idea poner texto fijos en el código, así que lo ideal es modificarlo añadiendo una constante de la siguiente forma:
 +
 +<sxh js>
 +app.constant("​algoritmo","​SHA-1"​);​
 +app.config(["​hashProvider","​algoritmo",​function(hashProvider,​algoritmo) {
 +  hashProvider.setAlgoritmo(algoritmo);​
 +}]);
 +</​sxh>​
 +  * Línea 1: Creamos la constante con el valor del algoritmo, que en este caso es "​SHA-1"​.
 +  * Línea 2: Inyectamos la constante en el bloque config
 +  * Línea 3: Establecemos el algoritmo que debe usar el ''​provider''​ llamado ''​hash''​ con el valor de la constante.
 +
 +Pero, ¿no habíamos hecho todo ésto para evitar usar la constante?​!!!!!! Sí, y seguimos sin hacerlo. Lo que queríamos era que el ''​provider''​ no usara directamente la constante y sigue sin hacerlo. Esta nueva constante realmente formaría parte de nuestra aplicación y no del ''​provider'',​ así que lo que estamos mejorando es nuestra propia aplicación y no el ''​provider'',​ que gracias a ser un ''​provider''​ es perfectamente personalizable y no depende de ninguna constante.
 +===== Ejemplo =====
 +Podemos ver ahora el ejemplo completo.
 +
 +<sxh html;​title:​index.html>​
 +<​!DOCTYPE html>
 +<html ng-app="​app">​
 +
 +  <​head>​
 +    <script src="//​ajax.googleapis.com/​ajax/​libs/​angularjs/​1.2.19/​angular.min.js"></​script>​
 +    <script src="​script.js"></​script>​
 +    <script src="​http://​crypto-js.googlecode.com/​svn/​tags/​3.1.2/​build/​rollups/​md5.js"></​script>​
 +    <script src="​http://​crypto-js.googlecode.com/​svn/​tags/​3.1.2/​build/​rollups/​sha1.js"></​script>​
 +    <script src="​http://​crypto-js.googlecode.com/​svn/​tags/​3.1.2/​build/​rollups/​sha256.js"></​script>​
 +    <script src="​http://​crypto-js.googlecode.com/​svn/​tags/​3.1.2/​build/​rollups/​sha512.js"></​script>​
 +    <script src="​http://​crypto-js.googlecode.com/​svn/​tags/​3.1.2/​build/​components/​enc-base64-min.js"></​script>​
 +  </​head>​
 +
 +  <body ng-controller="​PruebaController">​
 +    Contrase&​ntilde;​a:<​input ng-model="​password"​ />
 +    <br>
 +    El hash de la contrase&​ntilde;​a es:
 +    <br>
 +    {{getHash(password)}}
 +  </​body>​
 +</​html>​
 +</​sxh>​
 +
 +<sxh js;​title:​script.js>​
 +var app=angular.module("​app",​[]);​
 +
 +app.constant("​algoritmo","​SHA-1"​);​
 +
 +
 +function HashProvider() {
 +  var _algoritmo="";​
 +  ​
 +  this.setAlgoritmo=function(algoritmo) {
 +    _algoritmo=algoritmo;​
 +  };
 +  ​
 +  this.$get=function() {
 +    var hashFunction;​
 +  ​
 +    if (_algoritmo==="​MD5"​) {
 +      hashFunction=CryptoJS.MD5;​
 +    } else  if (_algoritmo==="​SHA-1"​) {
 +      hashFunction=CryptoJS.SHA1;​
 +    } else  if (_algoritmo==="​SHA-2-256"​) {
 +      hashFunction=CryptoJS.SHA256;​
 +    } else  if (_algoritmo==="​SHA-2-512"​) {
 +      hashFunction=CryptoJS.SHA512;​
 +    } else {
 +      throw Error("​El tipo de algoritmo no es válido:"​+_algoritmo);​
 +    }
 +  ​
 +    var hash=function(message) {
 +      var objHashResult=hashFunction(message);​
 +      ​
 +      var strHashResult=objHashResult.toString(CryptoJS.enc.Base64);​
 +    ​
 +      return strHashResult;​
 +    }
 +  ​
 +    return hash;
 +  }
 +}
 +
 +app.provider("​hash",​HashProvider);​
 +
 +
 +app.config(["​hashProvider","​algoritmo",​function(hashProvider,​algoritmo) {
 +  hashProvider.setAlgoritmo(algoritmo);​
 +}]);
 +
 +app.controller("​PruebaController",​["​$scope","​hash",​function($scope,​hash) {
 +  $scope.password="​s3cret";​
 +  $scope.getHash=function(message) {
 +    var hashResult=hash(message);​
 +    return hashResult;
 +  }
 +}]);
 +</​sxh>​
 +
 +
 +{{url>​http://​embed.plnkr.co/​PUXsjE}}
 +===== Repasando los tipos de servicios =====
 +Ahora es hora de que vuelvas a repasar el tema [[unidades:​03_servicios:​04_tiposservicios]] y ver si ahora lo entiendes todo perfectamente.
 +
  
 +<note important>​
 +Repasa el tema [[unidades:​03_servicios:​04_tiposservicios]]
 </​note>​ </​note>​
 +===== Referencias =====
 +  * [[https://​docs.angularjs.org/​guide/​providers#​provider-recipe|/​ Developer Guide / Providers / Provider Recipe]]
unidades/03_servicios/09_provider.1406732669.txt.gz · Última modificación: 2014/07/30 17:04 por admin
Ir hasta arriba
CC Attribution-Share Alike 3.0 Unported
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0