Pregunta AngularJS: Servicio vs proveedor vs fábrica


¿Cuáles son las diferencias entre un Service, Provider y Factory en AngularJS?


3163
2018-03-27 17:59


origen


Respuestas:


De la lista de correo de AngularJS conseguí un hilo increíble eso explica el servicio vs fábrica vs proveedor y su uso de inyección. Compilando las respuestas:

Servicios

Sintaxis: module.service( 'serviceName', function ); 
Resultado: al declarar ServiceName como un argumento inyectable se le proporcionará una instancia de la función. En otras palabras  new FunctionYouPassedToService().

Suerte

Sintaxis: module.factory( 'factoryName', function ); 
Resultado: al declarar FactoryName como un argumento inyectable, se le proporcionará el valor que se devuelve al invocar la referencia de función pasada a module.factory.

Proveedores

Sintaxis: module.provider( 'providerName', function ); 
Resultado: al declarar providerName como un argumento inyectable se te proporcionará  (new ProviderFunction()).$get(). La función constructora se instancia antes de llamar al método $ get - ProviderFunction es la referencia de función pasada a module.provider.

Los proveedores tienen la ventaja de que pueden configurarse durante la fase de configuración del módulo.

Ver aquí para el código proporcionado.

Aquí hay una gran explicación adicional de Misko:

provide.value('a', 123);

function Controller(a) {
  expect(a).toEqual(123);
}

En este caso, el inyector simplemente devuelve el valor tal como está. Pero, ¿y si quieres calcular el valor? Entonces usa una fábrica

provide.factory('b', function(a) {
  return a*2;
});

function Controller(b) {
  expect(b).toEqual(246);
}

Asi que factory es una función que es responsable de crear el valor. Tenga en cuenta que la función de fábrica puede solicitar otras dependencias.

Pero, ¿y si quieres ser más OO y tener una clase llamada Greeter?

function Greeter(a) {
  this.greet = function() {
    return 'Hello ' + a;
  }
}

Entonces, para crear una instancia, deberías escribir

provide.factory('greeter', function(a) {
  return new Greeter(a);
});

Entonces podríamos pedir 'bienvenida' en un controlador como este

function Controller(greeter) {
  expect(greeter instanceof Greeter).toBe(true);
  expect(greeter.greet()).toEqual('Hello 123');
}

Pero eso es demasiado prolijo. Una forma más corta de escribir esto sería provider.service('greeter', Greeter);

Pero, ¿y si quisiéramos configurar el Greeter clase antes de la inyección? Entonces podríamos escribir

provide.provider('greeter2', function() {
  var salutation = 'Hello';
  this.setSalutation = function(s) {
    salutation = s;
  }

  function Greeter(a) {
    this.greet = function() {
      return salutation + ' ' + a;
    }
  }

  this.$get = function(a) {
    return new Greeter(a);
  };
});

Entonces podemos hacer esto:

angular.module('abc', []).config(function(greeter2Provider) {
  greeter2Provider.setSalutation('Halo');
});

function Controller(greeter2) {
  expect(greeter2.greet()).toEqual('Halo 123');
}

Como nota al margen, service, factoryy value todos se derivan del proveedor.

provider.service = function(name, Class) {
  provider.provide(name, function() {
    this.$get = function($injector) {
      return $injector.instantiate(Class);
    };
  });
}

provider.factory = function(name, factory) {
  provider.provide(name, function() {
    this.$get = function($injector) {
      return $injector.invoke(factory);
    };
  });
}

provider.value = function(name, value) {
  provider.factory(name, function() {
    return value;
  });
};

2800
2017-07-30 10:20



Demostración de JS Fiddle

Ejemplo de "Hola mundo" con factory / service / provider:

var myApp = angular.module('myApp', []);

//service style, probably the simplest one
myApp.service('helloWorldFromService', function() {
    this.sayHello = function() {
        return "Hello, World!";
    };
});

//factory style, more involved but more sophisticated
myApp.factory('helloWorldFromFactory', function() {
    return {
        sayHello: function() {
            return "Hello, World!";
        }
    };
});
    
//provider style, full blown, configurable version     
myApp.provider('helloWorld', function() {

    this.name = 'Default';

    this.$get = function() {
        var name = this.name;
        return {
            sayHello: function() {
                return "Hello, " + name + "!";
            }
        }
    };

    this.setName = function(name) {
        this.name = name;
    };
});

//hey, we can configure a provider!            
myApp.config(function(helloWorldProvider){
    helloWorldProvider.setName('World');
});
        

function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {
    
    $scope.hellos = [
        helloWorld.sayHello(),
        helloWorldFromFactory.sayHello(),
        helloWorldFromService.sayHello()];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
    {{hellos}}
</div>
</body>


796
2018-05-15 15:53



TL; DR 

1) Cuando estás usando un Fábrica creas un objeto, le agregas propiedades y luego regresas ese mismo objeto. Cuando pase esta fábrica a su controlador, esas propiedades en el objeto ahora estarán disponibles en ese controlador a través de su fábrica.

app.controller(‘myFactoryCtrl’, function($scope, myFactory){
  $scope.artist = myFactory.getArtist();
});

app.factory(‘myFactory’, function(){
  var _artist = ‘Shakira’;
  var service = {};

  service.getArtist = function(){
    return _artist;
  }

  return service;
});


2) Cuando estás usando Servicio, AngularJS crea una instancia detrás de escena con la palabra clave 'nueva'. Por eso, agregará propiedades a 'esto' y el servicio devolverá 'esto'. Cuando pase el servicio a su controlador, esas propiedades en 'esto' ahora estarán disponibles en ese controlador a través de su servicio.

app.controller(‘myServiceCtrl’, function($scope, myService){
  $scope.artist = myService.getArtist();
});

app.service(‘myService’, function(){
  var _artist = ‘Nelly’;
  this.getArtist = function(){
    return _artist;
  }
});



3)  Proveedores son el único servicio que puede pasar a su función .config (). Utilice un proveedor cuando desee proporcionar una configuración de todo el módulo para su objeto de servicio antes de ponerlo a disposición.

app.controller(‘myProvider’, function($scope, myProvider){
  $scope.artist = myProvider.getArtist();
  $scope.data.thingFromConfig = myProvider.thingOnConfig;
});

app.provider(‘myProvider’, function(){
 //Only the next two lines are available in the app.config()
 this._artist = ‘’;
 this.thingFromConfig = ‘’;
  this.$get = function(){
    var that = this;
    return {
      getArtist: function(){
        return that._artist;
      },
      thingOnConfig: that.thingFromConfig
    }
  }
});

app.config(function(myProviderProvider){
  myProviderProvider.thingFromConfig = ‘This was set in config’;
});



Non TL; DR

1) Fábrica 
Las fábricas son la forma más popular de crear y configurar un servicio. Realmente no hay mucho más de lo que dijo el TL; DR. Usted acaba de crear un objeto, agregarle propiedades y luego devolver ese mismo objeto. Luego, cuando pasa la fábrica a su controlador, esas propiedades en el objeto ahora estarán disponibles en ese controlador a través de su fábrica. Un ejemplo más extenso está debajo.

app.factory(‘myFactory’, function(){
  var service = {};
  return service;
});

Ahora cualquier propiedad que adjuntemos a 'servicio' estará disponible para nosotros cuando pasemos 'myFactory' a nuestro controlador.

Ahora agreguemos algunas variables 'privadas' a nuestra función de devolución de llamada. Estos no serán accesibles directamente desde el controlador, pero eventualmente configuraremos algunos métodos getter / setter en 'servicio' para poder alterar estas variables 'privadas' cuando sea necesario.

app.factory(‘myFactory’, function($http, $q){
  var service = {};
  var baseUrl = ‘https://itunes.apple.com/search?term=’;
  var _artist = ‘’;
  var _finalUrl = ‘’;

  var makeUrl = function(){
   _artist = _artist.split(‘ ‘).join(‘+’);
    _finalUrl = baseUrl + _artist + ‘&callback=JSON_CALLBACK’;
    return _finalUrl
  }

  return service;
});

Aquí notará que no estamos asociando esas variables / función a 'servicio'. Simplemente los creamos para usarlos o modificarlos más tarde.

  • baseUrl es la URL base que requiere la API de iTunes
  • _artist es el artista que queremos buscar
  • _finalUrl es la URL final y completamente construida a la que realizaremos la llamada a iTunes
  • makeUrl es una función que creará y devolverá nuestra URL fácil de iTunes.

Ahora que nuestras variables y funciones auxiliares / privadas están en su lugar, agreguemos algunas propiedades al objeto 'servicio'. Todo lo que ponemos en 'servicio' se puede usar directamente dentro del controlador al que le pasemos 'myFactory'.

Vamos a crear los métodos setArtist y getArtist que simplemente devuelven o configuran el artista. También vamos a crear un método que llame a la API de iTunes con nuestra URL creada. Este método devolverá una promesa que se cumplirá una vez que los datos hayan regresado de la API de iTunes. Si no has tenido mucha experiencia en el uso de promesas en AngularJS, te recomiendo que hagas una inmersión profunda en ellas.

Abajo setArtist acepta un artista y le permite configurar el artista. getArtist regresa el artista callItunes primero llama a makeUrl () para construir la URL que usaremos con nuestra solicitud de $ http. Luego configura un objeto de promesa, realiza una solicitud de $ http con nuestra url final, y luego porque $ http devuelve una promesa, podemos llamar a .success o .error después de nuestra solicitud. Luego resolvemos nuestra promesa con los datos de iTunes, o lo rechazamos con un mensaje que dice 'Hubo un error'.

app.factory('myFactory', function($http, $q){
  var service = {};
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  service.setArtist = function(artist){
    _artist = artist;
  }

  service.getArtist = function(){
    return _artist;
  }

  service.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

  return service;
});

Ahora nuestra fábrica está completa. Ahora podemos insertar 'myFactory' en cualquier controlador y luego podremos llamar a nuestros métodos que adjuntamos a nuestro objeto de servicio (setArtist, getArtist y callItunes).

app.controller('myFactoryCtrl', function($scope, myFactory){
  $scope.data = {};
  $scope.updateArtist = function(){
    myFactory.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myFactory.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

En el controlador anterior, estamos inyectando en el servicio 'myFactory'. Luego establecemos propiedades en nuestro objeto $ scope con datos de 'myFactory'. El único código engañoso de arriba es si nunca antes has tratado con las promesas. Debido a que callItunes está devolviendo una promesa, podemos utilizar el método .then () y solo establecer $ scope.data.artistData una vez que nuestra promesa se cumpla con los datos de iTunes. Notarás que nuestro controlador es muy "delgado" (esta es una buena práctica de codificación). Toda nuestra lógica y datos persistentes se encuentran en nuestro servicio, no en nuestro controlador.

2) Servicio 
Quizás lo más importante que debe saberse cuando se trata de crear un Servicio es que se crea una instancia con la palabra clave 'nueva'. Para tus gurús de JavaScript esto debería darte una gran pista sobre la naturaleza del código. Para aquellos de ustedes con un conocimiento limitado en JavaScript o para aquellos que no están muy familiarizados con lo que realmente hace la palabra clave 'nueva', repasemos algunos fundamentos de JavaScript que eventualmente nos ayudarán a comprender la naturaleza de un Servicio.

Para ver realmente los cambios que ocurren cuando se invoca una función con la palabra clave 'nueva', vamos a crear una función e invocarla con la palabra clave 'nueva', luego mostraremos qué hace el intérprete cuando ve la palabra clave 'nueva'. Los resultados finales serán los mismos.

Primero, creemos nuestro Constructor.

var Person = function(name, age){
  this.name = name;
  this.age = age;
}

Esta es una función típica de constructor de JavaScript. Ahora cada vez que invocamos la función Person usando la palabra clave 'new', 'this' se vinculará al objeto recién creado.

Ahora agreguemos un método al prototipo de nuestra Persona para que esté disponible en cada instancia de nuestra "clase" de personas.

Person.prototype.sayName = function(){
  alert(‘My name is ‘ + this.name);
}

Ahora, porque ponemos la función sayName en el prototipo, cada instancia de Person podrá llamar a la función sayName para alertar el nombre de esa instancia.

Ahora que tenemos nuestra función constructor de persona y nuestra función sayName en su prototipo, creemos realmente una instancia de Person y luego llamemos a la función sayName.

var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’

De modo que todos juntos el código para crear un constructor de persona, agregar una función a su prototipo, crear una instancia de persona y llamar a la función en su prototipo se ve así.

var Person = function(name, age){
  this.name = name;
  this.age = age;
}
Person.prototype.sayName = function(){
  alert(‘My name is ‘ + this.name);
}
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’

Ahora veamos qué está sucediendo realmente cuando usas la palabra clave 'nueva' en JavaScript. Lo primero que debe observar es que después de usar 'nuevo' en nuestro ejemplo, podemos llamar a un método (sayName) en 'tyler' como si fuera un objeto, porque es así. Entonces, primero, sabemos que nuestro constructor de persona devuelve un objeto, ya sea que podamos verlo en el código o no. En segundo lugar, sabemos que debido a que nuestra función sayName está ubicada en el prototipo y no directamente en la instancia de la persona, el objeto que la función Persona está devolviendo debe delegar en su prototipo en las búsquedas fallidas. En términos más simples, cuando llamamos a tyler.sayName () el intérprete dice "OK, voy a ver el objeto 'tyler' que acabo de crear, ubico la función sayName, luego la llamo. Espera un minuto, no lo veo aquí, todo lo que veo es nombre y edad, déjame ver el prototipo. Sí, parece que está en el prototipo, déjame llamarlo ".

A continuación, encontrará un código sobre cómo puede pensar acerca de qué está haciendo realmente la palabra clave "nueva" en JavaScript. Básicamente es un ejemplo de código del párrafo anterior. He puesto la "vista del intérprete" o la forma en que el intérprete ve el código dentro de las notas.

var Person = function(name, age){
  //The below line creates an object(obj) that will delegate to the person’s prototype on failed lookups.
  //var obj = Object.create(Person.prototype);

  //The line directly below this sets ‘this’ to the newly created object
  //this = obj;

  this.name = name;
  this.age = age;

  //return this;
}

Ahora que tiene este conocimiento de lo que realmente hace la palabra clave "nueva" en JavaScript, la creación de un Servicio en AngularJS debería ser más fácil de entender.

Lo más importante para comprender al crear un servicio es saber que los servicios se instancian con la palabra clave 'nueva'. Combinando ese conocimiento con nuestros ejemplos anteriores, ahora debe reconocer que va a adjuntar sus propiedades y métodos directamente a 'esto', que luego será devuelto por el Servicio mismo. Echemos un vistazo a esto en acción.

A diferencia de lo que hicimos originalmente con el ejemplo de fábrica, no necesitamos crear un objeto y luego devolver ese objeto porque, como se mencionó muchas veces antes, usamos la palabra clave 'nueva' para que el intérprete cree ese objeto, haga que delegue en es un prototipo, luego devuélvanoslo sin que tengamos que hacer el trabajo.

Lo primero es lo primero, creemos nuestra función 'privada' y de ayuda. Esto debería ser muy familiar ya que hicimos exactamente lo mismo con nuestra fábrica. No voy a explicar lo que hace cada línea aquí porque lo hice en el ejemplo de fábrica, si está confundido, vuelva a leer el ejemplo de fábrica.

app.service('myService', function($http, $q){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }
});

Ahora, adjuntaremos todos nuestros métodos que estarán disponibles en nuestro controlador a 'esto'.

app.service('myService', function($http, $q){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  this.setArtist = function(artist){
    _artist = artist;
  }

  this.getArtist = function(){
    return _artist;
  }

  this.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

});

Ahora, al igual que en nuestra fábrica, setArtist, getArtist y callItunes estarán disponibles en cualquier controlador que pase myService. Aquí está el controlador myService (que es casi exactamente el mismo que nuestro controlador de fábrica).

app.controller('myServiceCtrl', function($scope, myService){
  $scope.data = {};
  $scope.updateArtist = function(){
    myService.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myService.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

Como mencioné antes, una vez que realmente entiende lo que 'nuevo' hace, los Servicios son casi idénticos a las fábricas en AngularJS.

3) Proveedor

Lo más importante que debe recordar sobre los proveedores es que son el único servicio que puede pasar a la porción de la aplicación de configuración de la aplicación. Esto es de gran importancia si necesita modificar alguna parte de su objeto de servicio antes de que esté disponible en cualquier otro lugar de su aplicación. Aunque es muy similar a Servicios / Fábricas, hay algunas diferencias que discutiremos.

Primero configuramos nuestro Proveedor de una manera similar a como lo hicimos con nuestro Servicio y Fábrica. Las variables a continuación son nuestra función 'privada' y de ayuda.

app.provider('myProvider', function(){
   var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  //Going to set this property on the config function below.
  this.thingFromConfig = ‘’;

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }
}

* Nuevamente, si alguna parte del código anterior es confusa, consulte la sección de Fábrica donde explico lo que hace para obtener más detalles.

Puede pensar en proveedores que tienen tres secciones. La primera sección es las variables / funciones 'privadas' que se modificarán / establecerán más tarde (como se muestra arriba). La segunda sección es de las variables / funciones que estarán disponibles en su función app.config y, por lo tanto, están disponibles para su modificación antes de que estén disponibles en otro lugar (también se muestra arriba). Es importante tener en cuenta que esas variables deben adjuntarse a la palabra clave 'this'. En nuestro ejemplo, solo 'thingFromConfig' estará disponible para modificar en la aplicación.config. La tercera sección (que se muestra a continuación) son todas las variables / funciones que estarán disponibles en su controlador cuando pase el servicio 'myProvider' a ese controlador específico.

Al crear un servicio con Proveedor, las únicas propiedades / métodos que estarán disponibles en su controlador son aquellas propiedades / métodos que se devuelven desde la función $ get (). El siguiente código pone $ get en 'this' (que sabemos que eventualmente será devuelto por esa función). Ahora, esa función $ get devuelve todos los métodos / propiedades que queremos que estén disponibles en el controlador. Aquí hay un ejemplo de código.

this.$get = function($http, $q){
    return {
      callItunes: function(){
        makeUrl();
        var deferred = $q.defer();
        $http({
          method: 'JSONP',
          url: _finalUrl
        }).success(function(data){
          deferred.resolve(data);
        }).error(function(){
          deferred.reject('There was an error')
        })
        return deferred.promise;
      },
      setArtist: function(artist){
        _artist = artist;
      },
      getArtist: function(){
        return _artist;
      },
      thingOnConfig: this.thingFromConfig
    }
  }

Ahora el código de Proveedor completo se ve así

app.provider('myProvider', function(){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  //Going to set this property on the config function below
  this.thingFromConfig = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  this.$get = function($http, $q){
    return {
      callItunes: function(){
        makeUrl();
        var deferred = $q.defer();
        $http({
          method: 'JSONP',
          url: _finalUrl
        }).success(function(data){
          deferred.resolve(data);
        }).error(function(){
          deferred.reject('There was an error')
        })
        return deferred.promise;
      },
      setArtist: function(artist){
        _artist = artist;
      },
      getArtist: function(){
        return _artist;
      },
      thingOnConfig: this.thingFromConfig
    }
  }
});

Ahora, al igual que en nuestra fábrica y Servicio, setArtist, getArtist y callItunes estarán disponibles en cualquier controlador que pase myProvider. Aquí está el controlador myProvider (que es casi exactamente el mismo que nuestro controlador de fábrica / Servicio).

app.controller('myProviderCtrl', function($scope, myProvider){
  $scope.data = {};
  $scope.updateArtist = function(){
    myProvider.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myProvider.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }

  $scope.data.thingFromConfig = myProvider.thingOnConfig;
});

Como se mencionó anteriormente, el objetivo de crear un servicio con el Proveedor es poder modificar algunas variables a través de la función app.config antes de que el objeto final pase al resto de la aplicación. Veamos un ejemplo de eso.

app.config(function(myProviderProvider){
  //Providers are the only service you can pass into app.config
  myProviderProvider.thingFromConfig = 'This sentence was set in app.config. Providers are the only service that can be passed into config. Check out the code to see how it works';
});

Ahora puede ver cómo 'thingFromConfig' es una cadena vacía en nuestro proveedor, pero cuando eso aparece en el DOM, será 'Esta oración se configuró ...'.


618
2017-12-24 13:15



Todos los servicios son singletons; se crean instancias una vez por aplicación. Ellos pueden ser de cualquier tipo, ya sea una función primitiva, literal de objeto, o incluso una instancia de un tipo personalizado.

los value, factory, service, constanty provider los métodos son todos proveedores Enseñan al inyector cómo crear instancias de los servicios.

El más detallado, pero también el más completo es un Proveedor   receta. los los cuatro restantes tipos de receta: valor, fábrica, servicio y   Constante - son solo azúcar sintáctico sobre una receta de proveedor.

  • los Receta de valor es el caso más simple, donde crea usted mismo el Servicio y proporciona el valor instanciado al inyector.
  • los Receta de fábrica le da al Inyector una función de fábrica que llama cuando necesita crear una instancia del servicio. Cuando se llama, el función de fábrica crea y devuelve la instancia del servicio. Las dependencias del Servicio se inyectan como argumentos de las funciones. Entonces, usar esta receta agrega las siguientes habilidades:
    • Posibilidad de usar otros servicios (tener dependencias)
    • Inicialización del servicio
    • Inicialización retrasada / floja
  • los Receta de servicio es casi lo mismo que la receta de fábrica, pero aquí el inyector invoca un constructor con el nuevo operador en lugar de una función de fábrica.
  • los Receta del proveedor es usualmente exagerado. Agrega una capa más de indirección al permitirle configurar la creación de la fábrica.

Debe usar la receta de proveedor solo cuando quiera exponer una API   para la configuración de toda la aplicación que debe realizarse antes del   la aplicación comienza. Esto generalmente es interesante solo para reutilizable   servicios cuyo comportamiento podría necesitar variar ligeramente entre   aplicaciones.


506
2018-02-01 12:58



Comprender AngularJS Factory, Service and Provider

Todos estos se utilizan para compartir objetos únicos reutilizables. Ayuda a compartir código reutilizable en su aplicación / varios componentes / módulos.

De Docs Servicio / Fábrica:

  • Instanciado perezosamente - Angular solo instancia un servicio / fábrica cuando un componente de la aplicación depende de él.
  • Singletons - Cada componente   Depende de un servicio obtiene una referencia a la instancia única   generado por la fábrica de servicio.

Fábrica

Una fábrica es una función donde puede manipular / agregar lógica antes de crear un objeto, luego se devuelve el objeto recién creado.

app.factory('MyFactory', function() {
    var serviceObj = {};
    //creating an object with methods/functions or variables
    serviceObj.myFunction = function() {
        //TO DO:
    };
    //return that object
    return serviceObj;
});

Uso

Puede ser solo una colección de funciones como una clase. Por lo tanto, puede crearse una instancia en diferentes controladores cuando lo está inyectando dentro de sus funciones de controlador / fábrica / directiva. Se crea una instancia solo una vez por aplicación.

Servicio

Simplemente mientras mira los servicios, piense en el prototipo de matriz. Un servicio es una función que instancia un nuevo objeto usando la palabra clave 'nueva'. Puede agregar propiedades y funciones a un objeto de servicio usando el thispalabra clave. A diferencia de una fábrica, no devuelve nada (devuelve un objeto que contiene métodos / propiedades).

app.service('MyService', function() {
    //directly binding events to this context
    this.myServiceFunction = function() {
        //TO DO:
    };
});

Uso

Úselo cuando necesite compartir un solo objeto en toda la aplicación. Por ejemplo, detalles de usuarios autenticados, métodos / datos compartibles, funciones de utilidad, etc.

Proveedor

Un proveedor se usa para crear un objeto de servicio configurable. Puede configurar la configuración del servicio desde la función de configuración. Devuelve un valor usando el $get() función. los $get la función se ejecuta en la fase de ejecución en angular.

app.provider('configurableService', function() {
    var name = '';
    //this method can be be available at configuration time inside app.config.
    this.setName = function(newName) {
        name = newName;
    };
    this.$get = function() {
        var getName = function() {
             return name;
        };
        return {
            getName: getName //exposed object to where it gets injected.
        };
    };
});

Uso

Cuando necesite proporcionar una configuración de módulo para su objeto de servicio antes de ponerlo a disposición, p. Ej. supongamos que desea establecer su URL de API en función de su entorno, como dev, stage o prod

NOTA 

Solo el proveedor estará disponible en la fase de configuración de angular, mientras   servicio y fábrica no lo son.

Espero que esto haya aclarado tu entendimiento sobre Fábrica, Servicio y Proveedor.


221
2017-11-14 06:25



Para mí, la revelación llegó cuando me di cuenta de que todos funcionan de la misma manera: al ejecutar algo una vez, almacenando el valor que obtienen, y luego tosen ese mismo valor almacenado cuando se hace referencia a través de inyección de dependencia.

Digamos que tenemos:

app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);

La diferencia entre los tres es que:

  1. aEl valor almacenado proviene de correr fn.
  2. bEl valor almacenado proviene de newEn g fn.
  3. cEl valor almacenado proviene de obtener primero una instancia newEn g fn, y luego ejecutar un $get método de la instancia.

Lo que significa que hay algo así como un objeto de caché dentro de AngularJS, cuyo valor de cada inyección solo se asigna una vez, cuando se han inyectado por primera vez, y donde:

cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()

Es por eso que usamos this en servicios, y define una this.$get en proveedores.


190
2017-07-22 11:39



Servicio vs proveedor vs fábrica:

Estoy tratando de mantenerlo simple. Se trata de un concepto básico de JavaScript.

Antes que nada, hablemos de servicios en AngularJS!

¿Qué es el Servicio? En AngularJS, Servicio no es más que un objeto de JavaScript único que puede almacenar algunos métodos o propiedades útiles. Este objeto singleton se crea por aplicación ngApp (aplicación angular) y se comparte entre todos los controladores dentro de la aplicación actual. Cuando Angularjs crea una instancia de un objeto de servicio, registra este objeto de servicio con un nombre de servicio único. Entonces, cada vez que necesitamos una instancia de servicio, Angular busca en el registro el nombre de este servicio y devuelve la referencia al objeto de servicio. De tal forma que podemos invocar el método, las propiedades de acceso, etc. en el objeto de servicio. Puede tener dudas si también puede poner propiedades, métodos en el objeto de alcance de los controladores. Entonces, ¿por qué necesitas un objeto de servicio? Respuestas es: los servicios se comparten entre el alcance del controlador múltiple. Si coloca algunas propiedades / métodos en el objeto de alcance de un controlador, estará disponible solo para el alcance actual. Pero cuando defines métodos, propiedades en el objeto de servicio, estará disponible globalmente y se puede acceder en el alcance de cualquier controlador inyectando ese servicio.

Entonces, si hay tres ámbitos de controlador, que sean el controlador A, el controlador B y el controlador C, todos compartirán la misma instancia de servicio.

<div ng-controller='controllerA'>
    <!-- controllerA scope -->
</div>
<div ng-controller='controllerB'>
    <!-- controllerB scope -->
</div>
<div ng-controller='controllerC'>
    <!-- controllerC scope -->
</div>

Cómo crear un servicio?

AngularJS proporciona diferentes métodos para registrar un servicio. Aquí nos concentraremos en tres métodos fábrica (...), servicio (...), proveedor (...);

Use este enlace para referencia de código

Función de fábrica:

Podemos definir una función de fábrica como a continuación.

factory('serviceName',function fnFactory(){ return serviceInstance;})

AngularJS proporciona 'factory (' serviceName ', fnFactory)' método que toma dos parámetros, serviceName y una función de JavaScript. Angular crea una instancia de servicio invocando la función fnFactory () como a continuación.

var serviceInstace = fnFactory();

La función aprobada puede definir un objeto y devolver ese objeto. AngularJS simplemente almacena esta referencia de objeto a una variable que se pasa como primer argumento. Todo lo que se devuelve desde fnFactory estará vinculado a serviceInstance. En lugar de devolver el objeto, también podemos devolver la función, los valores, etc. Lo que devolveremos estará disponible para la instancia de servicio.

Ejemplo:

var app= angular.module('myApp', []);
//creating service using factory method
app.factory('factoryPattern',function(){
  var data={
    'firstName':'Tom',
    'lastName':' Cruise',
    greet: function(){
      console.log('hello!' + this.firstName + this.lastName);
    }
  };

  //Now all the properties and methods of data object will be available in our service object
  return data;
});

Función de servicio:

service('serviceName',function fnServiceConstructor(){})

Es de otra manera, podemos registrar un servicio. La única diferencia es la forma en que AngularJS intenta crear una instancia del objeto de servicio. Esta vez angular utiliza la palabra clave 'nueva' y llama a la función constructora algo como a continuación.

var serviceInstance = new fnServiceConstructor();

En la función constructora podemos usar 'this' palabra clave para agregar propiedades / métodos al objeto de servicio. ejemplo:

//Creating a service using the service method
var app= angular.module('myApp', []);
app.service('servicePattern',function(){
  this.firstName ='James';
  this.lastName =' Bond';
  this.greet = function(){
    console.log('My Name is '+ this.firstName + this.lastName);
  };
});

Función del proveedor:

La función de proveedor () es la otra forma de crear servicios. Vamos a interesarnos en crear un servicio que muestre solo un mensaje de saludo al usuario. Pero también queremos proporcionar una funcionalidad tal que el usuario pueda establecer su propio mensaje de saludo. En términos técnicos, queremos crear servicios configurables. Cómo podemos hacer esto ? Debe haber una manera, para que la aplicación pueda pasar sus mensajes de saludo personalizados y Angularjs lo pondría a disposición de la función de fábrica / constructor que crea nuestra instancia de servicios. En tal caso, la función provider () hace el trabajo. utilizando la función provider () podemos crear servicios configurables.

Podemos crear servicios configurables utilizando la sintaxis del proveedor como se indica a continuación.

/*step1:define a service */
app.provider('service',function serviceProviderConstructor(){});

/*step2:configure the service */
app.config(function configureService(serviceProvider){});

¿Cómo funciona internamente la sintaxis del proveedor?

1. El objeto proveedor se crea usando la función de constructor que definimos en nuestra función de proveedor.

var serviceProvider = new serviceProviderConstructor();

2. La función que pasamos en app.config (), se ejecuta. Esto se llama fase de configuración, y aquí tenemos la posibilidad de personalizar nuestro servicio.

configureService(serviceProvider);

3. Por último, la instancia de servicio se crea llamando al método $ get de serviceProvider.

serviceInstance = serviceProvider.$get()

Código de muestra para crear un servicio que utiliza sintaxis:

var app= angular.module('myApp', []);
app.provider('providerPattern',function providerConstructor(){
  //this function works as constructor function for provider
  this.firstName = 'Arnold ';
  this.lastName = ' Schwarzenegger' ;
  this.greetMessage = ' Welcome, This is default Greeting Message' ;
  //adding some method which we can call in app.config() function
  this.setGreetMsg = function(msg){
    if(msg){
      this.greetMessage =  msg ;
    }
  };

  //We can also add a method which can change firstName and lastName
  this.$get = function(){
    var firstName = this.firstName;
    var lastName = this.lastName ;
    var greetMessage = this.greetMessage;
    var data={
       greet: function(){
         console.log('hello, ' + firstName + lastName+'! '+ greetMessage);
       }
    };
    return data ;
  };
});

app.config(
  function(providerPatternProvider){
    providerPatternProvider.setGreetMsg(' How do you do ?');
  }
);

Demo de trabajo

Resumen:


Fábrica use una función de fábrica que devuelva una instancia de servicio. serviceInstance = fnFactory ();

Servicio use una función de constructor y Angular invoque esta función de constructor usando la palabra clave 'nueva' para crear la instancia de servicio. serviceInstance = new fnServiceConstructor ();

Proveedor define una función providerConstructor, esta función providerConstructor define una función de fábrica $ get . Angular llama a $ get () para crear el objeto de servicio. La sintaxis del proveedor tiene la ventaja adicional de configurar el objeto de servicio antes de que se cree una instancia. serviceInstance = $ get ();


133
2017-11-19 13:36



Como señalaron varias personas aquí correctamente, una fábrica, proveedor, servicio e incluso valor y constante son versiones de la misma cosa. Puedes diseccionar el más general provider en todos ellos. Al igual que:

enter image description here

Aquí está el artículo de esta imagen es:

http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/


79
2017-08-02 05:37



Fábrica

Dale a AngularJS una función, AngularJS guardará en caché e inyectará el valor de retorno cuando se solicite la fábrica.

Ejemplo:

app.factory('factory', function() {
    var name = '';
    // Return value **is** the object that will be injected
    return {
        name: name;
    }
})

Uso:

app.controller('ctrl', function($scope, factory) {
     $scope.name = factory.name;
});

Servicio

Dale a AngularJS una función, AngularJS llamará nuevo para crear una instancia. Es la instancia que crea AngularJS que se almacenará en caché y se inyectará cuando se solicite el servicio. Ya que nuevo se usó para crear una instancia del servicio, la palabra clave esta es válido y se refiere a la instancia.

Ejemplo:

app.service('service', function() {
     var name = '';
     this.setName = function(newName) {
         name = newName;
     }
     this.getName = function() {
         return name;
     }
});

Uso:

app.controller('ctrl', function($scope, service) {
   $scope.name = service.getName();
});

Proveedor

Le da a AngularJS una función, y AngularJS llamará a su $get función. Es el valor de retorno de la $get función que se almacenará en caché e inyectará cuando se solicite el servicio.

Los proveedores le permiten configurar el proveedor antes de AngularJS llama al $get método para obtener el inyectable.

Ejemplo:

app.provider('provider', function() {
     var name = '';
     this.setName = function(newName) {
          name = newName;
     }
     this.$get = function() {
         return {
            name: name
         }
     }
})

Uso (como un inyectable en un controlador)

app.controller('ctrl', function($scope, provider) {
    $scope.name = provider.name;
});

Uso (configurar el proveedor antes $get es llamado para crear el inyectable)

app.config(function(providerProvider) {
    providerProvider.setName('John');
});

62
2018-05-19 19:53