dependency-injection factory - AngularJS:Servicio vs proveedor vs fábrica




example servicios (25)

Según los propósitos de la memoria, los controladores se crean instancias solo cuando son necesarios y se descartan cuando no son necesarios. Debido a esto, cada vez que cambia una ruta o recarga una página, Angular limpia el controlador actual. Sin embargo, los servicios proporcionan un medio para mantener los datos durante toda la vida útil de una aplicación, mientras que también se pueden usar en diferentes controladores de manera consistente.

Angular nos proporciona tres formas de crear y registrar nuestro propio servicio.

1) Fábrica

2) servicio

3) Proveedor

Fábrica : una fábrica es una función simple que le permite agregar algo de lógica antes de crear el objeto. Devuelve el objeto creado.

Es solo una colección de funciones como una clase. Por lo tanto, se puede crear una instancia en diferentes controladores cuando se usa con la función de constructor.

Servicio : Un servicio es una función constructora que crea el objeto utilizando una nueva palabra clave. Puede agregar propiedades y funciones a un objeto de servicio usando esta palabra clave. A diferencia de la fábrica, no devuelve nada.

Es un objeto singleton. Úselo cuando necesite compartir un solo objeto a través de la aplicación. Por ejemplo, detalles de usuarios autenticados.

Proveedor : un proveedor se utiliza para crear un objeto de servicio configurable. Devuelve valor utilizando la función $ get ().

Cuando necesite proporcionar una configuración por módulos para su objeto de servicio antes de que esté disponible.

Ejecute el siguiente código y vea la salida.

<!DOCTYPE html>
<html ng-app="app">
<head>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
    <meta charset=utf-8 />
    <title>JS Bin</title>
</head>
<body ng-controller="MyCtrl">
    {{serviceOutput}}
    <br/><br/>
    {{factoryOutput}}
    <br/><br/>
    {{providerOutput}}
    <script>
        var app = angular.module( 'app', [] );
        var MyFunc = function() {
            this.name = "default name";
            this.$get = function() {
                this.name = "new name"
                return "Hello from MyFunc.$get(). this.name = " + this.name;
            };
            return "Hello from MyFunc(). this.name = " + this.name;
        };
        // returns the actual function
        app.service( 'myService', MyFunc );
        // returns the function's return value
        app.factory( 'myFactory', MyFunc );
        // returns the output of the function's $get function
        app.provider( 'myProv', MyFunc );
        function MyCtrl( $scope, myService, myFactory, myProv ) {
            $scope.serviceOutput = "myService = " + myService;
            $scope.factoryOutput = "myFactory = " + myFactory;
            $scope.providerOutput = "myProvider = " + myProv;
        }
    </script>
</body>
</html>

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


Para mí, la mejor y más sencilla manera de entender la diferencia es:

var service, factory;
service = factory = function(injection) {}

Cómo AngularJS crea una instancia de componentes particulares (simplificados):

// service
var angularService = new service(injection);

// factory
var angularFactory = factory(injection);

Entonces, para el servicio, lo que se convierte en el componente AngularJS es la instancia de objeto de la clase representada por la función de declaración de servicio. Para la fábrica, es el resultado devuelto de la función de declaración de fábrica. La fábrica puede comportarse igual que el servicio:

var factoryAsService = function(injection) {
  return new function(injection) {
    // Service content
  }
}

La forma más simple de pensar es la siguiente:

  • El servicio es una instancia de objeto singleton. Utilice servicios si desea proporcionar un objeto singleton para su código.
  • La fábrica es una clase. Use fábricas si desea proporcionar clases personalizadas para su código (no se puede hacer con servicios porque ya están instanciados).

El ejemplo de 'clase' de fábrica se proporciona en los comentarios, así como la diferencia del proveedor.


Servicio vs proveedor vs fábrica:

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

En primer lugar, ¡hablemos de servicios en AngularJS!

Qué es el Servicio: En AngularJS, Serviciono es más que un objeto JavaScript singleton que puede almacenar algunos métodos o propiedades útiles. Este objeto singleton se crea según la base 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 este nombre de servicio y devuelve la referencia al objeto de servicio. De tal forma que podamos invocar métodos, propiedades de acceso, etc. en el objeto de servicio. ¡Puede tener dudas sobre si también puede poner propiedades, métodos en el objeto de alcance de los controladores! Entonces, ¿por qué necesita un objeto de servicio? Las respuestas son: los servicios se comparten entre varios controladores. Si coloca algunas propiedades / métodos en el objeto de alcance de un controlador, solo estará disponible para el alcance actual.Pero cuando defina métodos, propiedades en el objeto de servicio, estará disponible globalmente y se podrá acceder a él en cualquier ámbito del controlador inyectando ese servicio.

Entonces, si hay tres ámbitos de controlador, sea controladorA, controladorB y controladorC, 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 de fábrica (..), servicio (..), proveedor (..);

Utilice este enlace para referencia de código

Función de fábrica:

Podemos definir una función de fábrica de la siguiente manera.

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

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

var serviceInstace = fnFactory();

La función pasada 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 devuelva 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 usa la palabra clave 'nueva' y llama a la función de constructor algo como a continuación.

var serviceInstance = new fnServiceConstructor();

En la función de constructor, podemos usar la palabra clave 'this' 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 de proveedor:

La función Proveedor () es la otra forma de crear servicios. Permítanos crear un servicio que solo muestre un mensaje de saludo al usuario. Pero también queremos proporcionar una funcionalidad tal que el usuario pueda configurar su propio mensaje de saludo. En términos técnicos queremos crear servicios configurables. Cómo podemos hacer esto ? Debe haber una forma, para que la aplicación pueda pasar sus mensajes de saludo personalizados y Angularjs la pondría a disposición para la función de fábrica / constructor que crea nuestra instancia de servicios. En tal caso, la función proveedor () hace el trabajo. Utilizando la función de proveedor () 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 la sintaxis del proveedor internamente?

1.El objeto del proveedor se crea utilizando 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 oportunidad de personalizar nuestro servicio.

configureService(serviceProvider);

3. La instancia de servicio final se crea llamando al método $ get de serviceProvider.

serviceInstance = serviceProvider.$get()

Código de ejemplo para crear un servicio utilizando la sintaxis de proporcionar:

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 utiliza una función de fábrica que devuelve una instancia de servicio. serviceInstance = fnFactory ();

El servicio utiliza una función de constructor y Angular invoca esta función de constructor usando la palabra clave 'nuevo' para crear la instancia de servicio. serviceInstance = new fnServiceConstructor ();

El proveedor define una función providerConstructor, esta función providerConstructor define una función de fábrica $ get . Llamadas angulares $ get () para crear el objeto de servicio. La sintaxis del proveedor tiene una ventaja adicional de configurar el objeto de servicio antes de que se ejecute. serviceInstance = $ get ();


Resumen de docs.angularjs.org/guide/providers :

  • Hay cinco tipos de recetas que definen cómo crear objetos: Value , Factory , Service , Provider y Constant .
  • Fábrica y Servicio son las recetas más utilizadas. La única diferencia entre ellos es que la receta del Servicio funciona mejor para objetos de un tipo personalizado, mientras que la Fábrica puede producir funciones y funciones primitivas de JavaScript.
  • La receta del proveedor es el tipo de receta principal y todas las demás son solo azúcar sintáctica.
  • El proveedor es el tipo de receta más complejo. No lo necesita a menos que esté creando una pieza de código reutilizable que necesite configuración global.

Las mejores respuestas de SO:

https://.com/a/26924234/165673 (<- GOOD) https://.com/a/27263882/165673
https://.com/a/16566144/165673


Aquí hay un código de placa de la parrilla que he creado como una plantilla de código para la fábrica de objetos en AngularjS. He usado un Car / CarFactory como ejemplo para ilustrar. Hace para el código de implementación simple en el controlador.

     <script>
        angular.module('app', [])
            .factory('CarFactory', function() {

                /**
                 * BroilerPlate Object Instance Factory Definition / Example
                 */
                this.Car = function() {

                    // initialize instance properties
                    angular.extend(this, {
                        color           : null,
                        numberOfDoors   : null,
                        hasFancyRadio   : null,
                        hasLeatherSeats : null
                    });

                    // generic setter (with optional default value)
                    this.set = function(key, value, defaultValue, allowUndefined) {

                        // by default,
                        if (typeof allowUndefined === 'undefined') {
                            // we don't allow setter to accept "undefined" as a value
                            allowUndefined = false;
                        }
                        // if we do not allow undefined values, and..
                        if (!allowUndefined) {
                            // if an undefined value was passed in
                            if (value === undefined) {
                                // and a default value was specified
                                if (defaultValue !== undefined) {
                                    // use the specified default value
                                    value = defaultValue;
                                } else {
                                    // otherwise use the class.prototype.defaults value
                                    value = this.defaults[key];
                                } // end if/else
                            } // end if
                        } // end if

                        // update 
                        this[key] = value;

                        // return reference to this object (fluent)
                        return this;

                    }; // end this.set()

                }; // end this.Car class definition

                // instance properties default values
                this.Car.prototype.defaults = {
                    color: 'yellow',
                    numberOfDoors: 2,
                    hasLeatherSeats: null,
                    hasFancyRadio: false
                };

                // instance factory method / constructor
                this.Car.prototype.instance = function(params) {
                    return new 
                        this.constructor()
                                .set('color',           params.color)
                                .set('numberOfDoors',   params.numberOfDoors)
                                .set('hasFancyRadio',   params.hasFancyRadio)
                                .set('hasLeatherSeats', params.hasLeatherSeats)
                    ;
                };

                return new this.Car();

            }) // end Factory Definition
            .controller('testCtrl', function($scope, CarFactory) {

                window.testCtrl = $scope;

                // first car, is red, uses class default for:
                // numberOfDoors, and hasLeatherSeats
                $scope.car1     = CarFactory
                                    .instance({
                                        color: 'red'
                                    })
                                ;

                // second car, is blue, has 3 doors, 
                // uses class default for hasLeatherSeats
                $scope.car2     = CarFactory
                                    .instance({
                                        color: 'blue',
                                        numberOfDoors: 3
                                    })
                                ;
                // third car, has 4 doors, uses class default for 
                // color and hasLeatherSeats
                $scope.car3     = CarFactory
                                    .instance({
                                        numberOfDoors: 4
                                    })
                                ;
                // sets an undefined variable for 'hasFancyRadio',
                // explicitly defines "true" as default when value is undefined
                $scope.hasFancyRadio = undefined;
                $scope.car3.set('hasFancyRadio', $scope.hasFancyRadio, true);

                // fourth car, purple, 4 doors,
                // uses class default for hasLeatherSeats
                $scope.car4     = CarFactory
                                    .instance({
                                        color: 'purple',
                                        numberOfDoors: 4
                                    });
                // and then explicitly sets hasLeatherSeats to undefined
                $scope.hasLeatherSeats = undefined;
                $scope.car4.set('hasLeatherSeats', $scope.hasLeatherSeats, undefined, true);

                // in console, type window.testCtrl to see the resulting objects

            });
    </script>

Aquí hay un ejemplo más simple. Estoy usando algunas bibliotecas de terceros que esperan un objeto "Posición" que expone la latitud y la longitud, pero a través de diferentes propiedades del objeto. No quería hackear el código del proveedor, así que ajusté los objetos de "Posición" que estaba pasando.

    angular.module('app')
.factory('PositionFactory', function() {

    /**
     * BroilerPlate Object Instance Factory Definition / Example
     */
    this.Position = function() {

        // initialize instance properties 
        // (multiple properties to satisfy multiple external interface contracts)
        angular.extend(this, {
            lat         : null,
            lon         : null,
            latitude    : null,
            longitude   : null,
            coords: {
                latitude: null,
                longitude: null
            }
        });

        this.setLatitude = function(latitude) {
            this.latitude           = latitude;
            this.lat                = latitude;
            this.coords.latitude    = latitude;
            return this;
        };
        this.setLongitude = function(longitude) {
            this.longitude          = longitude;
            this.lon                = longitude;
            this.coords.longitude   = longitude;
            return this;
        };

    }; // end class definition

    // instance factory method / constructor
    this.Position.prototype.instance = function(params) {
        return new 
            this.constructor()
                    .setLatitude(params.latitude)
                    .setLongitude(params.longitude)
        ;
    };

    return new this.Position();

}) // end Factory Definition

.controller('testCtrl', function($scope, PositionFactory) {
    $scope.position1 = PositionFactory.instance({latitude: 39, longitude: 42.3123});
    $scope.position2 = PositionFactory.instance({latitude: 39, longitude: 42.3333});
}) // end controller

;


Mi aclaración sobre este asunto:

Básicamente, todos los tipos mencionados (servicio, fábrica, proveedor, etc.) están simplemente creando y configurando variables globales (que, por supuesto, son globales para toda la aplicación), al igual que las variables globales antiguas.

Si bien no se recomiendan las variables globales, el uso real de estas variables globales es proporcionar una inyección de dependencia , pasando la variable al controlador relevante.

Hay muchos niveles de complicaciones en la creación de los valores para las "variables globales":

  1. Constante
    Esto define una constante real que no debe modificarse durante toda la aplicación, al igual que las constantes en otros idiomas (algo que carece de JavaScript).
  2. Valor
    Este es un valor u objeto modificable, y sirve como una variable global, que incluso se puede inyectar al crear otros servicios o fábricas (consulte más adelante en estos). Sin embargo, debe ser un " valor literal ", lo que significa que uno tiene que escribir el valor real y no puede usar ningún cálculo o lógica de programación (en otras palabras, 39 o myText o {prop: "value"} están bien, pero 2 +2 no es).
  3. Fábrica
    Un valor más general, que se puede calcular de inmediato. Funciona al pasar una función a AngularJS con la lógica necesaria para calcular el valor y AngularJS lo ejecuta, y guarda el valor de retorno en la variable nombrada.
    Tenga en cuenta que es posible devolver un objeto (en cuyo caso funcionará de manera similar a un servicio ) o una función (que se guardará en la variable como una función de devolución de llamada).
  4. Servicio
    Un servicio es una versión más reducida de fábrica que es válida solo cuando el valor es un objeto, y permite escribir cualquier lógica directamente en la función (como si fuera un constructor), así como declarar y acceder a propiedades del objeto utilizando la palabra clave this .
  5. Proveedor
    A diferencia de un servicio que es una versión simplificada de fábrica , un proveedor es una forma más compleja, pero más flexible de inicializar las variables "globales", con la mayor flexibilidad como la opción para establecer valores desde app.config.
    Funciona como usar una combinación de servicio y proveedor , al pasar al proveedor una función que tiene propiedades declaradas usando esta palabra clave, que se pueden usar desde app.config.
    Luego, debe tener una función $ .get separada que se ejecuta mediante AngularJS después de configurar las propiedades anteriores a través del app.configarchivo, y esta función $ .get se comporta como la fábrica arriba, en que su valor de retorno se usa para inicializar las variables "globales".

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>


Fábrica: la fábrica en la que realmente creas un objeto dentro de la fábrica y lo devuelves.
servicio: el servicio que acaba de tener una función estándar que utiliza esta palabra clave para definir la función.
proveedor: El proveedor que hay un $ consigue que usted define y puede usarse para obtener el objeto que devuelve los datos.


Poco tarde a la fiesta. Pero pensé que esto es más útil para quienes deseen aprender (o tener claridad) sobre el desarrollo de los servicios personalizados de Angular JS utilizando metodologías de fábrica, servicio y proveedor.

Encontré este video que explica claramente sobre las metodologías de fábrica, servicio y proveedor para desarrollar los servicios personalizados de AngularJS:

https://www.youtube.com/watch?v=oUXku28ex-M

Código fuente: http://www.techcbt.com/Post/353/Angular-JS-basics/how-to-develop-angularjs-custom-service

El código publicado aquí se copia directamente de la fuente anterior, para beneficiar a los lectores.

El código para el servicio personalizado basado en "fábrica" ​​es el siguiente (que va con las versiones de sincronización y asíncrona junto con el servicio http de llamada):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcFactory',
  function($scope, calcFactory) {
    $scope.a = 10;
    $scope.b = 20;

    $scope.doSum = function() {
      //$scope.sum = calcFactory.getSum($scope.a, $scope.b); //synchronous
      calcFactory.getSum($scope.a, $scope.b, function(r) { //aynchronous
        $scope.sum = r;
      });
    };

  }
]);

app.factory('calcFactory', ['$http', '$log',
  function($http, $log) {
    $log.log("instantiating calcFactory..");
    var oCalcService = {};

    //oCalcService.getSum = function(a,b){
    //	return parseInt(a) + parseInt(b);
    //};

    //oCalcService.getSum = function(a, b, cb){
    //	var s = parseInt(a) + parseInt(b);
    //	cb(s);
    //};

    oCalcService.getSum = function(a, b, cb) { //using http service

      $http({
        url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
        method: 'GET'
      }).then(function(resp) {
        $log.log(resp.data);
        cb(resp.data);
      }, function(resp) {
        $log.error("ERROR occurred");
      });
    };

    return oCalcService;
  }
]);

El código para la metodología de "servicio" para servicios personalizados (esto es bastante similar a 'fábrica', pero diferente desde el punto de vista de la sintaxis):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
	$scope.a = 10;
	$scope.b = 20;

	$scope.doSum = function(){
		//$scope.sum = calcService.getSum($scope.a, $scope.b);
		
		calcService.getSum($scope.a, $scope.b, function(r){
			$scope.sum = r;
		});		
	};

}]);

app.service('calcService', ['$http', '$log', function($http, $log){
	$log.log("instantiating calcService..");
	
	//this.getSum = function(a,b){
	//	return parseInt(a) + parseInt(b);
	//};

	//this.getSum = function(a, b, cb){
	//	var s = parseInt(a) + parseInt(b);
	//	cb(s);
	//};

	this.getSum = function(a, b, cb){
		$http({
			url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
			method: 'GET'
		}).then(function(resp){
			$log.log(resp.data);
			cb(resp.data);
		},function(resp){
			$log.error("ERROR occurred");
		});
	};

}]);

El código para la metodología de "proveedor" para servicios personalizados (esto es necesario, si desea desarrollar un servicio que pueda configurarse):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
	$scope.a = 10;
	$scope.b = 20;

	$scope.doSum = function(){
		//$scope.sum = calcService.getSum($scope.a, $scope.b);
		
		calcService.getSum($scope.a, $scope.b, function(r){
			$scope.sum = r;
		});		
	};

}]);

app.provider('calcService', function(){

	var baseUrl = '';

	this.config = function(url){
		baseUrl = url;
	};

	this.$get = ['$log', '$http', function($log, $http){
		$log.log("instantiating calcService...")
		var oCalcService = {};

		//oCalcService.getSum = function(a,b){
		//	return parseInt(a) + parseInt(b);
		//};

		//oCalcService.getSum = function(a, b, cb){
		//	var s = parseInt(a) + parseInt(b);
		//	cb(s);	
		//};

		oCalcService.getSum = function(a, b, cb){

			$http({
				url: baseUrl + '/Sum?a=' + a + '&b=' + b,
				method: 'GET'
			}).then(function(resp){
				$log.log(resp.data);
				cb(resp.data);
			},function(resp){
				$log.error("ERROR occurred");
			});
		};		

		return oCalcService;
	}];

});

app.config(['calcServiceProvider', function(calcServiceProvider){
	calcServiceProvider.config("http://localhost:4467");
}]);

Finalmente la UI que funciona con cualquiera de los servicios anteriores:

<html>
<head>
	<title></title>
	<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js" ></script>
	<script type="text/javascript" src="t03.js"></script>
</head>
<body ng-app="app">
	<div ng-controller="emp">
		<div>
			Value of a is {{a}},
			but you can change
			<input type=text ng-model="a" /> <br>

			Value of b is {{b}},
			but you can change
			<input type=text ng-model="b" /> <br>

		</div>
		Sum = {{sum}}<br>
		<button ng-click="doSum()">Calculate</button>
	</div>
</body>
</html>


Para mí, la revelación se produjo cuando me di cuenta de que todos funcionan de la misma manera: ejecutando algo una vez , almacenando el valor que obtienen y luego expulsan ese mismo valor almacenado cuando se hace referencia a través de la 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 viene de correr fn.
  2. bEl valor almacenado viene de newing fn.
  3. cque está almacenado el valor viene de obtener primero una instancia por newing fn, y luego la ejecución de un $getmétodo de la instancia.

Lo que significa que hay algo como un objeto de caché dentro de AngularJS, cuyo valor de cada inyección solo se asigna una vez, cuando se inyecta la primera vez, y donde

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

Es por eso que utilizamos thisen servicios, y definimos this.$geten proveedores.


Esencialmente, Proveedor, Fábrica y Servicio son todos los Servicios. Una Fábrica es un caso especial de un Servicio cuando todo lo que necesita es una función $ get (), que le permite escribirlo con menos código.

Las principales diferencias entre servicios, fábricas y proveedores son sus complejidades. Los servicios son la forma más simple, las fábricas son un poco más robustas y los proveedores se pueden configurar en tiempo de ejecución.

Aquí hay un resumen de cuándo usar cada uno:

Fábrica : el valor que está proporcionando debe calcularse en función de otros datos.

Servicio : Usted está devolviendo un objeto con métodos.

Proveedor : Desea poder configurar, durante la fase de configuración, el objeto que se creará antes de que se cree. Utilice el Proveedor principalmente en la configuración de la aplicación, antes de que la aplicación se haya inicializado completamente.


Todos los servicios son singletons ; se instancian una vez por aplicación. Pueden ser de cualquier tipo , ya sea primitivo, objeto literal, función o incluso una instancia de un tipo personalizado.

El value , la factory , el service , la constant y los métodos del provider son todos los proveedores. Enseñan al inyector cómo instanciar los servicios.

La más detallada, pero también la más completa, es una receta del Proveedor. Los cuatro tipos de recetas restantes (Valor, Fábrica, Servicio y Constante) son solo azúcar sintáctica además de una receta del proveedor .

  • La Receta de valor es el caso más simple, donde usted crea una instancia del Servicio y proporciona el valor de instancia al inyector.
  • La 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, la función de fábrica crea y devuelve la instancia de servicio. Las dependencias del Servicio se inyectan como argumentos de las funciones. Así que usando esta receta agrega las siguientes habilidades:
    • Posibilidad de utilizar otros servicios (tener dependencias)
    • Inicialización del servicio
    • Inicialización retardada / perezosa
  • La receta del Servicio es casi la misma 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.
  • La receta del proveedor suele ser una exageración . Añade una capa más de direccionamiento indirecto al permitirle configurar la creación de la fábrica.

    Debe usar la receta del proveedor solo cuando desee exponer una API para la configuración de toda la aplicación que debe realizarse antes de que se inicie la aplicación. Por lo general, esto es interesante solo para los servicios reutilizables cuyo comportamiento puede necesitar variar ligeramente entre las aplicaciones.

  • La receta Constante es como la receta de Valor, excepto que le permite definir servicios que están disponibles en la fase de configuración . Más temprano que los servicios creados utilizando la receta de valor. A diferencia de los valores, no pueden ser decorados usando decorator .
Consulte la documentación del proveedor .


TL; DR

1) Cuando está utilizando una Fábrica , crea un objeto, le agrega propiedades y luego devuelve 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 utiliza Service , AngularJS crea una instancia detrás de escena con la palabra clave "nuevo". Debido a 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) Los 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’;
});



No 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 que lo que dijo el TL; DR. Solo creas un objeto, le agregas propiedades y luego devuelves ese mismo objeto. Luego, cuando pase 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. A continuación se muestra un ejemplo más extenso.

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

Ahora, todas las propiedades que adjuntamos al 'servicio' estarán disponibles cuando pasemos 'myFactory' a nuestro controlador.

Ahora agreguemos algunas variables 'privadas' a nuestra función de devolución de llamada. No se podrá acceder directamente a estos desde el controlador, pero eventualmente estableceremos algunos métodos de obtención / configuración 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 adjuntando esas variables / función al 'servicio'. Simplemente los estamos creando para usarlos o modificarlos más tarde.

  • baseUrl es la URL base que requiere la API de iTunes
  • _artista es el artista que deseamos buscar.
  • _finalUrl es la URL final y totalmente integrada a la que haremos la llamada a iTunes
  • makeUrl es una función que creará y devolverá nuestra URL amigable de iTunes.

Ahora que nuestras funciones y variables de ayuda / privadas están en su lugar, agreguemos algunas propiedades al objeto 'servicio'. Cualquier cosa que pongamos en "servicio" puede usarse directamente dentro del controlador al que pasamos "myFactory".

Vamos a crear métodos setArtist y getArtist que simplemente devuelven o configuran el artista. También vamos a crear un método que llamará 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 tienes mucha experiencia en el uso de promesas en AngularJS, te recomiendo que hagas una inmersión profunda en ellas.

A continuación, setArtist acepta un artista y le permite configurar el artista. getArtist devuelve el artista. callItunes llama por primera vez a makeUrl () para construir la URL que usaremos con nuestra solicitud $ http. Luego configura un objeto de promesa, realiza una solicitud $ http con nuestra url final y, a continuación, debido a que $ 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 la 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 inyectar '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 de arriba, estamos inyectando en el servicio 'myFactory'. Luego establecemos propiedades en nuestro objeto $ scope con datos de 'myFactory'. El único código complicado anterior es si nunca antes has cumplido las promesas. Debido a que callItunes está devolviendo una promesa, podemos usar el método .then () y solo establecer $ scope.data.artistData una vez que nuestra promesa se cumpla con los datos de iTunes. Notará que nuestro controlador es muy 'delgado' (esta es una buena práctica de codificación). Todos nuestros datos lógicos y persistentes se encuentran en nuestro servicio, no en nuestro controlador.

2) servicio
Quizás lo más importante que se debe saber cuando se trata de crear un Servicio es que se crea una instancia con la palabra clave "nuevo". Para los gurús de JavaScript, esto debería darle una gran pista sobre la naturaleza del código. Para aquellos de ustedes con antecedentes limitados en JavaScript o para aquellos que no están muy familiarizados con lo que realmente hace la "nueva" palabra clave, revisemos algunos aspectos fundamentales de JavaScript que eventualmente nos ayudarán a entender la naturaleza de un Servicio.

Para ver realmente los cambios que ocurren cuando invoca una función con la palabra clave 'nueva', creemos una función y la invocamos con la palabra clave 'nueva', luego mostremos qué hace el intérprete cuando ve la palabra clave 'nueva'. Los resultados finales serán los mismos.

Primero vamos a crear nuestro Constructor.

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

Esta es una función constructora de JavaScript típica. Ahora, cada vez que invocamos la función Persona utilizando la palabra clave 'nuevo', 'esto' estará vinculado 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 Persona.

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

Ahora, debido a que 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 constructora Person y nuestra función sayName en su prototipo, creamos realmente una instancia de Person y luego llamamos a la función sayName.

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

Así que todos juntos el código para crear un constructor de Person, agregar una función a su prototipo, crear una instancia de Person y luego llamar a la función en su prototipo se parece a esto.

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 lo que realmente está sucediendo cuando usas la palabra clave 'nuevo' en JavaScript. Lo primero que debe notar es que después de usar 'nuevo' en nuestro ejemplo, podemos llamar a un método (sayName) en 'tyler' como si fuera un objeto, eso es porque lo es. Entonces, primero, sabemos que nuestro constructor Persona está devolviendo 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 se encuentra en el prototipo y no directamente en la instancia de Persona, el objeto que la función de Persona está devolviendo debe delegar a 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 buscar el objeto 'tyler' que acabamos de crear, localice la función sayName y luego llámela. Espera un momento, 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 se muestra el código para saber qué es lo que realmente hace la palabra clave 'nueva' en JavaScript. Es básicamente un ejemplo de código del párrafo anterior. He puesto la 'vista de 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 tenemos este conocimiento de lo que realmente hace la palabra clave 'nueva' en JavaScript, crear un Servicio en AngularJS debería ser más fácil de entender.

Lo más importante que se debe entender al crear un Servicio es saber que los Servicios se crean instancias con la palabra clave "nuevo". Combinando ese conocimiento con nuestros ejemplos anteriores, ahora debe reconocer que adjuntará sus propiedades y métodos directamente a 'esto', que luego será devuelto desde el propio Servicio. Echemos un vistazo a esto en acción.

A diferencia de lo que hicimos originalmente con el ejemplo de Factory, no necesitamos crear un objeto y luego devolver ese objeto porque, como se mencionó muchas veces antes, usamos la palabra clave 'nuevo' 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 parecer muy familiar ya que hicimos exactamente lo mismo con nuestra fábrica. No explicaré lo que hace cada línea aquí porque lo hice en el ejemplo de fábrica. Si estás confundido, vuelve 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 en el que pasemos 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 entiendes lo que hace 'nuevo', los Servicios son casi idénticos a las fábricas en AngularJS.

3) Proveedor

Lo más importante que debe recordar acerca de los proveedores es que son el único servicio que puede pasar a la parte app.config de su 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 son muy similares a los Servicios / Fábricas, hay algunas diferencias que discutiremos.

Primero configuramos a nuestro Proveedor de 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 en la que explico lo que hace más detalles.

Puedes pensar que los proveedores tienen tres secciones. La primera sección es las variables / funciones 'privadas' que se modificarán / establecerán más adelante (se muestra arriba). La segunda sección son las variables / funciones que estarán disponibles en su función app.config y, por lo tanto, están disponibles para modificarlas antes de que estén disponibles en cualquier 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 app.config. La tercera sección (que se muestra a continuación) contiene 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 el 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 código a continuación pone $ get en 'this' (que sabemos que finalmente se devolverá de 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 en el que pasemos 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 principal de crear un servicio con el Proveedor es poder alterar algunas variables a través de la función app.config antes de que el objeto final se 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 se muestre en el DOM, será 'Esta oración fue establecida ...'.


Después de leer todas estas publicaciones, creó más confusión para mí ... Pero aún así, toda la información es valiosa ... finalmente encontré la siguiente tabla que proporcionará información con una comparación simple

  • El inyector usa recetas para crear dos tipos de objetos: servicios y objetos de propósito especial
  • Hay cinco tipos de recetas que definen cómo crear objetos: Valor, Fábrica, Servicio, Proveedor y Constante.
  • Fábrica y Servicio son las recetas más utilizadas. La única diferencia entre ellos es que la receta del Servicio funciona mejor para objetos de un tipo personalizado, mientras que la Fábrica puede producir funciones y funciones primitivas de JavaScript.
  • La receta del proveedor es el tipo de receta principal y todas las demás son solo azúcar sintáctica.
  • El proveedor es el tipo de receta más complejo. No lo necesita a menos que esté creando una pieza de código reutilizable que necesite configuración global.
  • Todos los objetos de propósito especial, excepto el controlador, se definen a través de las recetas de fábrica.

Y para principiantes, comprenda: - Esto puede no corregir el caso de uso, pero en alto nivel es lo que usamos para estos tres.

  1. Si desea utilizar en el módulo angular la función de configuración debe crearse como proveedor.

angular.module('myApp').config(function($testProvider){
$testProvider.someFunction();
})

  1. La integración de llamadas ajax o de terceros debe ser un servicio .
  2. Para manipulaciones de datos crealo como fábrica.

Para escenarios básicos de fábrica y servicio se comporta igual.


Esta es una parte muy confusa para el novato y he tratado de aclararlo con palabras fáciles

AngularJS Service: se utiliza para compartir funciones de utilidad con la referencia de servicio en el controlador. El servicio tiene una naturaleza única, por lo que para un servicio solo se crea una instancia en el navegador y se utiliza la misma referencia en toda la página.

En el servicio, creamos nombres de funciones como propiedad con este objeto.

AngularJS Factory: el propósito de Factory también es el mismo que el Servicio, sin embargo, en este caso creamos un nuevo objeto y agregamos funciones como propiedades de este objeto y al final devolvemos este objeto.

AngularJS Provider: el propósito de esto es de nuevo igual, sin embargo, Provider proporciona la salida de su función $ get.

Definición y uso de Servicio, Fábrica y Proveedor se explican en http://www.dotnetfunda.com/articles/show/3156/difference-between-angularjs-service-factory-and-provider


Entendiendo AngularJS Fábrica, Servicio y Proveedor

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

Desde Docs Service/Factory :

  • Se ha creado una instancia perezosa : Angular solo crea una instancia de un servicio / fábrica cuando un componente de la aplicación depende de ello.
  • Singletons : cada componente que depende de un servicio obtiene una referencia a la instancia única generada por la fábrica de servicios.

Fábrica

Una fábrica es una función en la que 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, se puede crear una instancia en diferentes controladores cuando se está inyectando dentro de las funciones de controlador / fábrica / directiva. Se instancia solo una vez por aplicación.

Servicio

Simplemente mirando los servicios piensa en el prototipo de matriz. Un servicio es una función que crea una instancia de un nuevo objeto utilizando la palabra clave 'nuevo'. Puede agregar propiedades y funciones a un objeto de servicio usando this palabra 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 a lo largo de la aplicación. Por ejemplo, detalles de usuarios autenticados, métodos / datos que se pueden compartir, funciones de utilidad, etc.

Proveedor

Se utiliza un proveedor para crear un objeto de servicio configurable. Puede configurar la configuración del servicio desde la función de configuración. Devuelve un valor utilizando la función $get() . La función $get 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 por módulos para su objeto de servicio antes de ponerlo a disposición, por ejemplo. Supongamos que desea establecer la URL de su API en función de su entorno como dev, stageoprod

NOTA

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

Espero que esto haya aclarado su comprensión acerca de Fábrica, Servicio y Proveedor .


Mi entendimiento es muy simple a continuación.

Fábrica: Simplemente creas un objeto dentro de la fábrica y lo devuelves.

Servicio:

Solo tiene una función estándar que utiliza esta palabra clave para definir una función.

Proveedor:

Hay un $getobjeto que define y se puede usar para obtener el objeto que devuelve datos.


Fábrica

Le da a AngularJS una función, AngularJS almacenará 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

Le das a AngularJS una función, AngularJS llamará nueva para crear una instancia de ella. Es la instancia que crea AngularJS que se almacenará en caché e inyectará cuando se solicite el servicio. Dado que la nueva se utiliza para crear una instancia del servicio, la palabra clave esta es válida 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 das a AngularJS una función, y AngularJS llamará a su $getfunción. Es el valor de retorno de la $getfunción que se almacenará en caché e inyectará cuando se solicite el servicio.

Los proveedores le permiten configurar el proveedor antes de que AngularJS llame al $getmé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 (la configuración del proveedor antes $getse llama para crear el inyectable)

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

Discutamos las tres formas de manejar la lógica de negocios en AngularJS de una manera simple: ( Inspirado por el curso Coursera AngularJS de Yaakov )

SERVICIO :

Sintaxis:

app.js

 var app = angular.module('ServiceExample',[]);
 var serviceExampleController =
              app.controller('ServiceExampleController', ServiceExampleController);
 var serviceExample = app.service('NameOfTheService', NameOfTheService);

 ServiceExampleController.$inject = ['NameOfTheService'] //protects from minification of js files

function ServiceExampleController(NameOfTheService){
     serviceExampleController = this;
     serviceExampleController.data = NameOfTheService.getSomeData();
 }

function NameOfTheService(){
     nameOfTheService = this;
     nameOfTheService.data = "Some Data";
     nameOfTheService.getSomeData = function(){
           return nameOfTheService.data;
     }     
}

index.html

<div ng-controller = "ServiceExampleController as serviceExample">
   {{serviceExample.data}}
</div>

Características del servicio:

  1. Instancia perezosa : Si no se inyecta, no se instanciará nunca. Así que para usarlo habrá que inyectarlo a un módulo.
  2. Singleton : si se inyecta a varios módulos, todos tendrán acceso a una sola instancia en particular. Por eso es muy conveniente compartir datos a través de diferentes controladores.

FÁBRICA

Primero echemos un vistazo a la sintaxis:

app.js :

var app = angular.module('FactoryExample',[]);
var factoryController = app.controller('FactoryController', FactoryController);
var factoryExampleOne = app.factory('NameOfTheFactoryOne', NameOfTheFactoryOne);
var factoryExampleTwo = app.factory('NameOfTheFactoryTwo', NameOfTheFactoryTwo);

//first implementation where it returns a function
function NameOfTheFactoryOne(){
   var factory = function(){
      return new SomeService();
    }
   return factory;
}

//second implementation where an object literal would be returned
function NameOfTheFactoryTwo(){
   var factory = {
      getSomeService : function(){
          return new SomeService();
       }
    };
   return factory;
}

Ahora usando los dos anteriores en el controlador:

 var factoryOne = NameOfTheFactoryOne() //since it returns a function
 factoryOne.someMethod();

 var factoryTwo = NameOfTheFactoryTwo.getSomeService(); //accessing the object
 factoryTwo.someMethod();

Características de la fábrica:

  1. Sigue el patrón de diseño de fábrica. La fábrica es un lugar central que produce nuevos objetos o funciones.
  2. No solo produce singleton, sino servicios personalizables.
  3. El .service()método es una fábrica que siempre produce el mismo tipo de servicio, que es un singleton, y sin ninguna forma fácil de configurar su comportamiento. Ese .service()método generalmente se usa como acceso directo para algo que no requiere ninguna configuración en absoluto.

PROVEEDOR

Vamos a echar un vistazo a la sintaxis primero:

angular.module('ProviderModule', [])
.controller('ProviderModuleController', ProviderModuleController)
.provider('ServiceProvider', ServiceProvider)
.config(Config); //optional

Config.$inject = ['ServiceProvider'];
function Config(ServiceProvider) {
  ServiceProvider.defaults.maxItems = 10; //some default value
}


ProviderModuleController.$inject = ['ServiceProvider'];
function ProviderModuleController(ServiceProvider) {
  //some methods
}

function ServiceProvider() {
  var provider = this;

  provider.defaults = {
    maxItems: 10
  };

  provider.$get = function () {
    var someList = new someListService(provider.defaults.maxItems);

    return someList;
  };
}

}

Características del proveedor:

  1. Proveedor es el método más flexible de crear servicios en Angular.
  2. No solo podemos crear una fábrica que se puede configurar dinámicamente, sino que al momento de usar la fábrica, con el método del proveedor, podemos configurar la fábrica de manera personalizada solo una vez en el arranque de toda nuestra aplicación.
  3. La fábrica se puede utilizar en toda la aplicación con ajustes personalizados. En otras palabras, podemos configurar esta fábrica antes de que comience la aplicación. De hecho, en la documentación angular se menciona que el método del proveedor es lo que realmente se ejecuta detrás de la escena cuando configuramos nuestros servicios con uno .serviceo más .factorymétodos.
  4. El $getes una función que se une directamente a la instancia proveedor. Esa función es una función de fábrica . En otras palabras, es como el que usamos para proporcionar al .factorymétodo. En esa función, creamos nuestro propio servicio. Esta $getpropiedad, que es una función, es lo que hace que el proveedor sea un proveedor . AngularJS espera que el proveedor tenga una propiedad $ get cuyo valor es una función que Angular tratará como una función de fábrica. Pero lo que hace que la configuración de todo este proveedor sea muy especial, es el hecho de que podemos proporcionar algún configobjeto dentro del proveedor de servicios, y eso generalmente viene con valores predeterminados que luego podemos sobrescribir en el paso, donde podemos configurar toda la aplicación.

Conozco muchas respuestas excelentes, pero tengo que compartir mi experiencia de usar
1. servicepara la mayoría de los casos predeterminados
2. factoryutilizado para crear el servicio en esa instancia específica

// factory.js ////////////////////////////
(function() {
'use strict';
angular
    .module('myApp.services')
    .factory('xFactory', xFactoryImp);
xFactoryImp.$inject = ['$http'];

function xFactoryImp($http) {
    var fac = function (params) {
        this._params = params; // used for query params
    };

    fac.prototype.nextPage = function () {
        var url = "/_prc";

        $http.get(url, {params: this._params}).success(function(data){ ...
    }
    return fac;
}
})();

// service.js //////////////////////////
(function() {
'use strict';
angular
    .module('myApp.services')
    .service('xService', xServiceImp);
xServiceImp.$inject = ['$http'];

function xServiceImp($http) {  
    this._params = {'model': 'account','mode': 'list'};

    this.nextPage = function () {
        var url = "/_prc";

        $http.get(url, {params: this._params}).success(function(data){ ...
    }       
}
})();

y usando:

controller: ['xFactory', 'xService', function(xFactory, xService){

        // books = new instance of xFactory for query 'book' model
        var books = new xFactory({'model': 'book', 'mode': 'list'});

        // accounts = new instance of xFactory for query 'accounts' model
        var accounts = new xFactory({'model': 'account', 'mode': 'list'});

        // accounts2 = accounts variable
        var accounts2 = xService;
... 

1. Los servicios son objetos singleton que se crean cuando es necesario y nunca se limpian hasta el final del ciclo de vida de la aplicación (cuando se cierra el navegador). Los controladores se destruyen y se limpian cuando ya no son necesarios.

2. La forma más fácil de crear un servicio es usando el método factory (). El método factory () nos permite definir un servicio devolviendo un objeto que contiene funciones de servicio y datos de servicio. La función de definición de servicio es donde colocamos nuestros servicios inyectables, como $ http y $ q. Ex:

angular.module('myApp.services')
.factory('User', function($http) { // injectables go here
var backendUrl = "http://localhost:3000"; var service = {
    // our factory definition
user: {},
setName: function(newName) {
      service.user['name'] = newName;
    },
setEmail: function(newEmail) { service.user['email'] = newEmail;
},
save: function() {
return $http.post(backendUrl + '/users', { user: service.user
}); }
};
return service; });

Usando la fábrica () en nuestra aplicación

Es fácil utilizar la fábrica en nuestra aplicación, ya que simplemente podemos inyectarla donde la necesitamos en tiempo de ejecución.

angular.module('myApp')
.controller('MainController', function($scope, User) {
  $scope.saveUser = User.save;
});
  1. El método service (), por otro lado, nos permite crear un servicio mediante la definición de una función constructora. Podemos usar un objeto prototípico para definir nuestro servicio, en lugar de un objeto javascript en bruto. De manera similar al método factory (), también estableceremos los inyectables en la definición de la función.
  2. La forma de nivel más bajo para crear un servicio es mediante el método de provisión (). Esta es la única forma de crear un servicio que podemos configurar utilizando la función .config (). A diferencia de los métodos anteriores, configuraremos los inyectables en una definición de función $ get () definida.

Ya hay buenas respuestas, pero solo quiero compartir esta.

En primer lugar: Proveedor es la forma / receta para crear un service(objeto singleton) que se supone que debe inyectar el inyector $ (cómo AngulaJS se ocupa del patrón IoC).

Y Valor, Fábrica, Servicio y Constante (4 maneras): el azúcar sintáctico sobre el modo Proveedor / recepción.

Se Service vs Factoryha cubierto una parte: https://www.youtube.com/watch?v=BLzNCkPn3ao

El servicio tiene que ver con la newpalabra clave que, como sabemos, hace 4 cosas:

  1. crea nuevo objeto
  2. lo vincula a su prototypeobjeto
  3. se conecta contextathis
  4. y devuelve this

Y Factory tiene que ver con Factory Pattern: contiene funciones que devuelven Objetos como ese Servicio.

  1. Habilidad para usar otros servicios (tener dependencias).
  2. inicialización del servicio
  3. inicialización diferida / perezosa

Y este video simple / corto: cubre también al Proveedor : https://www.youtube.com/watch?v=HvTZbQ_hUZY (ahí puede ver cómo van de fábrica al proveedor)

La receta del proveedor se usa principalmente en la configuración de la aplicación, antes de que la aplicación se haya iniciado / inicializado completamente.


Como lo señalaron varias personas aquí, una fábrica, un proveedor, un servicio, e incluso un valor y una constante son versiones de lo mismo. Puedes diseccionar lo más general provideren todos ellos. Al igual que:

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


Solo para aclarar las cosas, desde la fuente de AngularJS, puede ver que un servicio simplemente llama a la función de fábrica que a su vez llama a la función de proveedor:

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

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

Mis pensamientos:

Dependecy Injection: pasar colaboradores como parámetros a los constructores. Marco de inyección de dependencias: una fábrica genérica y configurable para crear los objetos para pasar como parámetros a los constructores.





angularjs dependency-injection angularjs-service angularjs-factory angularjs-provider