Pregunta Confundido acerca de Servicio vs Fábrica


Según lo entiendo, cuando estoy dentro de una fábrica devuelvo un objeto que se inyecta en un controlador. Cuando dentro de un servicio estoy tratando con el objeto usando this y no devuelve nada

Estaba bajo el supuesto de que un servicio era siempre un singletony que un nuevo objeto de fábrica se inyecta en cada controlador. Sin embargo, como resultado, un objeto de fábrica es un singleton también?

Código de ejemplo para demostrar:

var factories = angular.module('app.factories', []);
var app = angular.module('app',  ['ngResource', 'app.factories']);

factories.factory('User', function () {
  return {
    first: 'John',
    last: 'Doe'
  };
});

app.controller('ACtrl', function($scope, User) {
  $scope.user = User;
});

app.controller('BCtrl', function($scope, User) {
  $scope.user = User;
});

Al cambiar user.first en ACtrl Resulta que user.first en BCtrl también se cambia, p. User es un singleton?

¿Mi suposición era que una nueva instancia se inyectó en un controlador con una fábrica?


593
2017-12-07 11:31


origen


Respuestas:


Todos los servicios angulares son singletons:

Documentos (ver Servicios como singletons) https://docs.angularjs.org/guide/services

Por último, es importante darse cuenta de que todos los servicios de Angular son singletons de aplicación. Esto significa que solo hay una instancia de un servicio determinado por inyector.

Básicamente, la diferencia entre el servicio y la fábrica es la siguiente:

app.service('myService', function() {

  // service is just a constructor function
  // that will be called with 'new'

  this.sayHello = function(name) {
     return "Hi " + name + "!";
  };
});

app.factory('myFactory', function() {

  // factory returns an object
  // you can run some code before

  return {
    sayHello : function(name) {
      return "Hi " + name + "!";
    }
  }
});

Vea esta presentación sobre $ provide: http://slides.wesalvaro.com/20121113/#/

Esas diapositivas se utilizaron en una de las reuniones de AngularJs: http://blog.angularjs.org/2012/11/more-angularjs-meetup-videos.html


585
2017-12-07 13:17



Para mí, la revelación vino 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 Dependency Injection.

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 , en otras palabras: fn()
  2. bEl valor almacenado proviene de newEn g fn, en otras palabras: new 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 angular, cuyo valor de cada inyección solo se asigna una vez, cuando se han inyectado la 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.

Espero que esto ayude.


361
2017-11-14 06:32



ejemplo en vivo

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() {
    // In the provider function, you cannot inject any
    // service or factory. This can only be done at the
    // "$get" method.

    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()];
}​

93
2017-10-28 13:50



También hay una manera de devolver una función de constructor para que pueda regresar nuevo clases en fábricas, como esta:

function MyObjectWithParam($rootScope, name) {
  this.$rootScope = $rootScope;
  this.name = name;
}
MyObjectWithParam.prototype.getText = function () {
  return this.name;
};

App.factory('MyObjectWithParam', function ($injector) {
  return function(name) { 
    return $injector.instantiate(MyObjectWithParam,{ name: name });
  };
}); 

Entonces puede hacer esto en un controlador que usa MyObjectWithParam:

var obj = new MyObjectWithParam("hello"),

Vea aquí el ejemplo completo:
http://plnkr.co/edit/GKnhIN?p=preview

Y aquí las páginas del grupo de google, donde se discutió:
https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ 


57
2018-04-09 14:39



Estas son las principales diferencias:

Servicios

Sintaxis: module.service( 'serviceName', function );

Resultado: al declarar ServiceName como un argumento inyectable, se le proporcionará el instancia de una función pasó a module.service.

Uso: podría ser útil para compartiendo funciones de utilidad que son útiles para invocar simplemente añadiendo () a la referencia de la función inyectada. También se podría ejecutar con injectedArg.call( this ) o similar.

Suerte

Sintaxis: module.factory( 'factoryName', function );

Resultado: cuando se declara factoryName como un argumento inyectable, se le proporcionará el valor que se devuelve al invocar la referencia de función pasó a module.factory.

Uso: podría ser útil para devolver un 'clase' función que luego puede ser renovada para crear instancias.

También verifica Documentación AngularJS y una pregunta similar en stackoverflow confundido acerca de servicio vs fábrica.

Aquí está ejemplo usando servicios y fábrica. Leer más sobre Servicio AngularJS vs fábrica.


50
2017-12-23 00:01



Agregando a la primera respuesta, creo que .service () es para las personas que han escrito su código en un estilo más orientado a objetos (C # / Java) (usando esta palabra clave y instanciando objetos a través de la función prototipo / Constructor).

Factory es para desarrolladores que escriben código que es más natural para javascript / estilo funcional de codificación.

Eche un vistazo al código fuente de .service y .factory method dentro de angular.js - internamente todos ellos llaman método de proveedor:

  function provider(name, provider_) {
    if (isFunction(provider_)) {
      provider_ = providerInjector.instantiate(provider_);
    }
    if (!provider_.$get) {
      throw Error('Provider ' + name + ' must define $get factory method.');
    }
    return providerCache[name + providerSuffix] = provider_;
  }

  function factory(name, factoryFn) { \
    return provider(name, { $get: factoryFn }); 
  }

  function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
  }

27
2018-06-20 11:35



Muy simple:

.service: la función registrada se invocará como un constructor (también conocido como 'newed')

.factory - la función registrada se invocará como una función simple

Ambos se invocan una vez, lo que resulta en un objeto singleton que se inyecta en otros componentes de la aplicación.


25
2017-11-25 14:17



Todos los proveedores trabajan de la misma manera. Los diferentes métodos service, factory, provider solo te permite lograr lo mismo en menos código.

PD También hay value y constant.

Cada caso especial en la cadena comenzando con provider y terminando con value tiene una limitación adicional Entonces, para decidir entre ellos, debes preguntarte qué puedes lograr con menos código.

Aquí hay una imagen que muestra lo que quiero decir:

enter image description here

Puede obtener una guía de referencia y referencia en la publicación del blog de la que obtuve esta imagen:

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


20
2017-12-10 13:02



Aquí hay algunos ejemplos más de servicios vs fábricas que pueden ser útiles para ver la diferencia entre ellos. Básicamente, un servicio tiene "nuevo ..." llamado, ya está instanciado. Una fábrica no se crea una instancia automáticamente.

Ejemplos básicos

Devuelve un objeto de clase que tiene un único método

Aquí hay un servicio que tiene un único método:

angular.service('Hello', function () {
  this.sayHello = function () { /* ... */ };
});

Aquí hay una fábrica que devuelve un objeto con un método:

angular.factory('ClassFactory', function () {
  return {
    sayHello: function () { /* ... */ }
  };
});

Devuelve un valor

Una fábrica que devuelve una lista de números:

angular.factory('NumberListFactory', function () {
  return [1, 2, 3, 4, 5];
});

console.log(NumberListFactory);

Un servicio que devuelve una lista de números:

angular.service('NumberLister', function () {
  this.numbers = [1, 2, 3, 4, 5];
});

console.log(NumberLister.numbers);

El resultado en ambos casos es el mismo, la lista de números.

Ejemplos avanzados

Variables de "clase" usando fábricas

En este ejemplo definimos un CounterFactory, incrementa o disminuye un contador y usted puede obtener el recuento actual u obtener cuántos objetos de CounterFactory se han creado:

angular.factory('CounterFactory', function () {
  var number_of_counter_factories = 0; // class variable

  return function () {
    var count = 0; // instance variable
    number_of_counter_factories += 1; // increment the class variable

    // this method accesses the class variable
    this.getNumberOfCounterFactories = function () {
      return number_of_counter_factories;
    };

    this.inc = function () {
      count += 1;
    };
    this.dec = function () {
      count -= 1;
    };
    this.getCount = function () {
      return count;
    };
  }

})

Usamos el CounterFactory para crear múltiples contadores. Podemos acceder a la variable de clase para ver cuántos contadores se crearon:

var people_counter;
var places_counter;

people_counter = new CounterFactory();
console.log('people', people_counter.getCount());
people_counter.inc();
console.log('people', people_counter.getCount());

console.log('counters', people_counter.getNumberOfCounterFactories());

places_counter = new CounterFactory();
console.log('places', places_counter.getCount());

console.log('counters', people_counter.getNumberOfCounterFactories());
console.log('counters', places_counter.getNumberOfCounterFactories());

El resultado de este código es:

people 0
people 1
counters 1
places 0
counters 2
counters 2

13
2017-07-29 07:56