dependency-injection $get - AngularJS:Service vs provider vs factory




$provide module (25)

Un ulteriore chiarimento è che le fabbriche possono creare funzioni / primitive, mentre i servizi non possono. jsFiddle un'occhiata a questo jsFiddle basato su Epokk: http://jsfiddle.net/skeller88/PxdSP/1351/ .

La factory restituisce una funzione che può essere invocata:

myApp.factory('helloWorldFromFactory', function() {
  return function() {
    return "Hello, World!";
  };
});

La factory può anche restituire un oggetto con un metodo che può essere invocato:

myApp.factory('helloWorldFromFactory', function() {
  return {
    sayHello: function() {
      return "Hello, World!";
    }
  };
});

Il servizio restituisce un oggetto con un metodo che può essere richiamato:

myApp.service('helloWorldFromService', function() {
  this.sayHello = function() {
     return "Hello, World!";
  };
});

Per maggiori dettagli, vedere un post che ho scritto sulla differenza: http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/

Quali sono le differenze tra un Service , Provider e Factory in AngularJS?


Questa risposta indirizza l'argomento / domanda

come Fabbrica, Servizio e Costante - sono solo zucchero sintattico in cima alla ricetta di un fornitore?

O

come fabbrica, servic e provider sono simailari internamente

in fondo quello che succede è

Quando si effettua un factory()set si functionfornisce in secondo argomento al provider $gete lo si restituisce ( provider(name, {$get:factoryFn })), tutto ciò che si ottiene è providerma non esiste alcuna proprietà / metodo diverso da$get quello provider(significa che non è possibile configurarlo)

Codice sorgente della fabbrica

function factory(name, factoryFn, enforce) {
    return provider(name, {
      $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
    });
};

Quando si effettua un service()ritorno si fornisce una factory () con una functionche inietta constructor(restituisce l'istanza della funzione di costruzione fornita nel servizio) e la restituisce

Codice sorgente del servizio

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

Quindi, in entrambi i casi, alla fine ottieni un provider $ ottieni la tua funzione che hai fornito, ma puoi dare qualcosa in più di $ get come puoi originariamente fornire in provider () per il blocco di configurazione


Ci sono già buone risposte, ma voglio solo condividere questo.

Prima di tutto: Provider è il modo / la ricetta per creare un serviceoggetto singleton che deve essere iniettato da $ injector (come AngulaJS segue il pattern IoC).

E Valore, Fabbrica, Servizio e Costante (4 modi): lo zucchero sintattico rispetto al modo / alle ricette del Fornitore .

C'è una Service vs Factoryparte è stata coperta: https://www.youtube.com/watch?v=BLzNCkPn3ao

Il servizio riguarda esclusivamente la newparola chiave che, come sappiamo, fa 4 cose:

  1. crea un oggetto nuovo di zecca
  2. lo collega al suo prototypeoggetto
  3. si connette contextathis
  4. e ritorna this

E Factory è tutto basato su Factory Pattern - contiene funzioni che restituiscono oggetti come quel servizio.

  1. possibilità di utilizzare altri servizi (avere dipendenze)
  2. inizializzazione del servizio
  3. inizializzazione ritardata / pigra

E questo semplice / breve video: copre anche Provider : https://www.youtube.com/watch?v=HvTZbQ_hUZY (lì puoi vedere come vanno dalla fabbrica al fornitore)

La ricetta del provider viene utilizzata principalmente nella configurazione dell'app, prima che l'app sia stata completamente avviata / inizializzata.


Per me, la rivelazione è arrivata quando ho capito che funzionano tutti allo stesso modo: eseguendo qualcosa una volta , memorizzando il valore che ottengono, e poi tossendo su quello stesso valore memorizzato quando si fa riferimento all'iniezione delle dipendenze .

Diciamo che abbiamo:

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

La differenza tra i tre è che:

  1. aIl valore memorizzato viene dalla corsa fn.
  2. bIl valore memorizzato proviene da newing fn.
  3. cIl valore memorizzato viene dal primo ottenimento di un'istanza mediante newing fne quindi dall'esecuzione di un $getmetodo dell'istanza.

Il che significa che c'è qualcosa come un oggetto cache all'interno di AngularJS, il cui valore di ciascuna iniezione viene assegnato una sola volta, quando sono stati iniettati la prima volta e dove:

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

Questo è il motivo per cui utilizziamo i thisservizi e definiamo un this.$getfornitore.


1. I servizi sono oggetti singleton che vengono creati quando necessario e non vengono mai ripuliti fino alla fine del ciclo di vita dell'applicazione (quando il browser è chiuso). I controllori vengono distrutti e ripuliti quando non sono più necessari.

2. Il modo più semplice per creare un servizio è utilizzare il metodo factory (). Il metodo factory () ci consente di definire un servizio restituendo un oggetto che contiene funzioni di servizio e dati di servizio. La funzione di definizione del servizio è dove posizioniamo i nostri servizi iniettabili, come $ http e $ 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 fabbrica () nella nostra app

È facile usare la fabbrica nella nostra applicazione poiché possiamo semplicemente iniettarla dove ne abbiamo bisogno in fase di esecuzione.

angular.module('myApp')
.controller('MainController', function($scope, User) {
  $scope.saveUser = User.save;
});
  1. Il metodo service (), d'altra parte, ci consente di creare un servizio definendo una funzione di costruzione. Possiamo utilizzare un oggetto prototipo per definire il nostro servizio, invece di un oggetto javascript non elaborato. Simile al metodo factory (), imposteremo anche gli iniettabili nella definizione della funzione.
  2. Il modo più basso per creare un servizio è utilizzando il metodo provide (). Questo è l'unico modo per creare un servizio che possiamo configurare usando la funzione .config (). A differenza dei metodi precedenti, imposterai gli iniettabili in una definizione definita di $ get ().

Tutti i servizi sono singleton ; vengono istanziati una volta per app. Possono essere di qualsiasi tipo , sia che si tratti di una primitiva, di un oggetto letterale, di una funzione, o persino di un'istanza di un tipo personalizzato.

I metodi di value , factory , service , constant e provider sono tutti i fornitori. Insegnano all'iniettore come istanziare i servizi.

Il più dettagliato, ma anche il più completo è una ricetta del provider. I restanti quattro tipi di ricetta - Valore, Fabbrica, Servizio e Costante - sono solo zucchero sintattico in cima a una ricetta del fornitore .

  • La Value Recipe è il caso più semplice, in cui istanziate il Servizio da soli e fornite il valore istanziato all'iniettore.
  • La ricetta di fabbrica fornisce all'iniettore una funzione di fabbrica che chiama quando è necessario istanziare il servizio. Quando viene chiamato, la funzione factory crea e restituisce l'istanza del servizio. Le dipendenze del Servizio vengono iniettate come argomenti delle funzioni. Quindi, usando questa ricetta aggiunge le seguenti abilità:
    • Possibilità di utilizzare altri servizi (avere dipendenze)
    • Inizializzazione del servizio
    • Inizializzazione ritardata / pigra
  • La ricetta di servizio è quasi la stessa della ricetta di fabbrica, ma qui l'iniettore invoca un costruttore con il nuovo operatore invece di una funzione di fabbrica.
  • La ricetta del fornitore è solitamente eccessiva . Aggiunge un ulteriore livello di riferimento indiretto, consentendo di configurare la creazione della fabbrica.

    È necessario utilizzare la ricetta Provider solo quando si desidera esporre un'API per la configurazione a livello di applicazione che deve essere eseguita prima dell'avvio dell'applicazione. Questo di solito è interessante solo per i servizi riutilizzabili il cui comportamento potrebbe dover variare leggermente tra le applicazioni.

  • La ricetta costante è uguale alla ricetta del valore, tranne che consente di definire i servizi disponibili nella fase di configurazione . Prima dei servizi creati utilizzando la ricetta Valore. A differenza dei valori, non possono essere decorati con decorator .
Vedi la documentazione del provider .


In sostanza, Provider, Factory e Service sono tutti servizi. Una Factory è un caso speciale di un Servizio quando tutto ciò di cui hai bisogno è una funzione $ get (), che ti consente di scriverlo con meno codice.

Le principali differenze tra servizi, fabbriche e fornitori sono le loro complessità. I servizi sono la forma più semplice, le fabbriche sono un po 'più robuste e i provider sono configurabili in fase di runtime.

Ecco un riepilogo di quando utilizzare ciascuno:

Fabbrica : il valore che stai fornendo deve essere calcolato sulla base di altri dati.

Servizio : stai restituendo un oggetto con metodi.

Provider : vuoi essere in grado di configurare, durante la fase di configurazione, l'oggetto che verrà creato prima della sua creazione. Utilizzare il provider principalmente nella configurazione dell'app, prima che l'app sia completamente inizializzata.


Fabbrica: la fabbrica crea effettivamente un oggetto all'interno della fabbrica e lo restituisce.
servizio: il servizio ha solo una funzione standard che utilizza questa parola chiave per definire la funzione.
provider: il provider dispone di $ get definisci e può essere utilizzato per ottenere l'oggetto che restituisce i dati.


Riepilogo da docs.angularjs.org/guide/providers :

  • Esistono cinque tipi di ricetta che definiscono come creare oggetti: Value , Factory , Service , Provider e Constant .
  • La fabbrica e il servizio sono le ricette più utilizzate. L'unica differenza tra loro è che la ricetta del servizio funziona meglio per oggetti di un tipo personalizzato, mentre la Factory può produrre primitive e funzioni JavaScript.
  • La ricetta del provider è il tipo di ricetta principale e tutti gli altri sono solo zucchero sintattico.
  • Il fornitore è il tipo di ricetta più complesso. Non ne hai bisogno a meno che non stai costruendo un pezzo di codice riutilizzabile che richiede una configurazione globale.

Migliori risposte da SO:

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


Servizio vs fornitore vs fabbrica:

Sto cercando di mantenerlo semplice. Riguarda il concetto base di JavaScript.

Prima di tutto, parliamo di servizi in AngularJS!

Cos'è il servizio: in AngularJS, servizionon è altro che un oggetto JavaScript singleton che può memorizzare alcuni metodi o proprietà utili. Questo oggetto singleton viene creato per base (app Angular) e viene condiviso tra tutti i controller all'interno dell'app corrente. Quando Angularjs crea un'istanza di un oggetto servizio, registra questo oggetto servizio con un nome di servizio univoco. Quindi ogni volta che abbiamo bisogno di un'istanza di servizio, Angular cerca nel registro il nome di questo servizio e restituisce il riferimento all'oggetto servizio. Tale che possiamo invocare il metodo, accedere alle proprietà ecc. Sull'oggetto servizio. Potresti avere una domanda se puoi anche mettere le proprietà, i metodi sull'oggetto scope dei controller! Allora perché hai bisogno di un oggetto di servizio? Le risposte sono: i servizi sono condivisi tra più ambiti di controllo. Se si inseriscono alcune proprietà / metodi nell'oggetto di un ambito del controllore, esso sarà disponibile solo per l'ambito corrente.Tuttavia, quando si definiscono i metodi, le proprietà sull'oggetto servizio, sarà disponibile a livello globale e si può accedere in qualsiasi ambito del controllore mediante l'iniezione di quel servizio.

Quindi, se ci sono tre scope del controller, sia controllerA, controllerB e controllerC, tutti condivideranno la stessa istanza di servizio.

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

Come creare un servizio?

AngularJS fornisce diversi metodi per registrare un servizio. Qui ci concentreremo su tre metodi factory (..), service (..), provider (..);

Usa questo link per il codice di riferimento

Funzione di fabbrica:

Possiamo definire una funzione di fabbrica come di seguito.

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

AngularJS fornisce il metodo factory ('serviceName', fnFactory) ' che accetta due parametri, serviceName e una funzione JavaScript. Angular crea un'istanza del servizio invocando la funzione fnFactory () come di seguito.

var serviceInstace = fnFactory();

La funzione passata può definire un oggetto e restituire quell'oggetto. AngularJS memorizza semplicemente questo riferimento oggetto a una variabile che viene passata come primo argomento. Tutto ciò che viene restituito da fnFactory sarà associato a serviceInstance. Invece di restituire un oggetto, possiamo anche restituire la funzione, i valori ecc. Qualsiasi cosa restituiremo, sarà disponibile per l'istanza del servizio.

Esempio:

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;
});

Funzione di servizio:

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

È l'altro modo, possiamo registrare un servizio. L'unica differenza è il modo in cui AngularJS tenta di creare un'istanza dell'oggetto servizio. Questa volta angolare utilizza la parola chiave "nuova" e chiama la funzione di costruzione qualcosa come di seguito.

var serviceInstance = new fnServiceConstructor();

Nella funzione di costruzione possiamo usare la parola chiave 'this' per aggiungere proprietà / metodi all'oggetto servizio. esempio:

//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);
  };
});

Funzione Provider:

La funzione Provider () è un altro modo per creare servizi. Cerchiamo di essere interessati a creare un servizio che mostri solo un messaggio di saluto all'utente. Ma vogliamo anche fornire una funzionalità tale che l'utente possa impostare il proprio messaggio di saluto. In termini tecnici, vogliamo creare servizi configurabili. Come possiamo farlo? Ci deve essere un modo, in modo che l'app possa passare i propri messaggi di saluto personalizzati e Angularjs lo renderebbe disponibile alla funzione factory / constructor che crea la nostra istanza di servizi. In tal caso, la funzione provider () esegue il lavoro. utilizzando la funzione provider () possiamo creare servizi configurabili.

Possiamo creare servizi configurabili usando la sintassi del provider come indicato di seguito.

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

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

Come funziona la sintassi del provider internamente?

L'oggetto 1.Provider viene creato utilizzando la funzione di costruzione definita nella nostra funzione provider.

var serviceProvider = new serviceProviderConstructor();

2. La funzione che abbiamo passato in app.config (), viene eseguita. Questa è chiamata fase di configurazione, e qui abbiamo la possibilità di personalizzare il nostro servizio.

configureService(serviceProvider);

3. L'istanza di servizio finale viene creata chiamando il metodo $ get di serviceProvider.

serviceInstance = serviceProvider.$get()

Il codice di esempio per la creazione del servizio utilizzando fornisce la sintassi:

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 di lavoro

Sommario:

Fabbrica usa una funzione di fabbrica che restituisce un'istanza di servizio. serviceInstance = fnFactory ();

Il servizio utilizza una funzione di costruzione e Angular richiama questa funzione di costruzione utilizzando la parola chiave 'new' per creare l'istanza del servizio. serviceInstance = new fnServiceConstructor ();

Il provider definisce una funzione providerConstructor, questa funzione providerConstructor definisce una funzione factory $ get . Chiamate angolari $ get () per creare l'oggetto servizio. La sintassi del provider ha un ulteriore vantaggio di configurare l'oggetto servizio prima che venga istanziato. serviceInstance = $ get ();


Come sottolineato da più persone qui correttamente, una fabbrica, un fornitore, un servizio e persino un valore e una costante sono versioni della stessa cosa. Puoi sezionare il più generale providerin tutti loro. Così:

Ecco l'articolo di questa immagine tratta da:


Questa è una parte molto confusa per principianti e ho cercato di chiarirlo in parole semplici

Servizio AngularJS: viene utilizzato per condividere le funzioni di utilità con il riferimento del servizio nel controller. Il servizio è di natura singleton, quindi per un solo servizio viene creata un'istanza nel browser e lo stesso riferimento viene utilizzato in tutta la pagina.

Nel servizio, creiamo nomi di funzioni come proprietà con questo oggetto.

AngularJS Factory: lo scopo di Factory è lo stesso di Service, tuttavia in questo caso creiamo un nuovo oggetto e aggiungiamo funzioni come proprietà di questo oggetto e alla fine restituiamo questo oggetto.

Provider AngularJS: lo scopo di questo è di nuovo lo stesso, tuttavia Provider fornisce l'output della sua funzione $ get.

La definizione e l'utilizzo di Service, Factory e Provider sono spiegati all'indirizzo http://www.dotnetfunda.com/articles/show/3156/difference-between-angularjs-service-factory-and-provider


Conosco molte ottime risposte, ma devo condividere la mia esperienza sull'uso di
1. serviceper la maggior parte dei casi di default
2. factoryutilizzato per creare il servizio di quell'istanza specifica

// 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){ ...
    }       
}
})();

e 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;
... 

Ho notato qualcosa di interessante quando giocavo con i provider.

La visibilità degli iniettabili è diversa per i fornitori rispetto a servizi e fabbriche. Se dichiari una "costante" di AngularJS (ad esempio myApp.constant('a', 'Robert');), puoi inserirla in servizi, fabbriche e fornitori.

Ma se si dichiara un "valore" di AngularJS (ad esempio., myApp.value('b', {name: 'Jones'});), È possibile inserirlo nei servizi e nelle fabbriche, ma NON nella funzione di creazione del provider. Tuttavia, è possibile iniettarlo nella $getfunzione che si definisce per il proprio provider. Questo è menzionato nella documentazione di AngularJS, ma è facile non vederlo. Puoi trovarlo nella pagina% di fornitura nelle sezioni relative al valore e ai metodi costanti.

http://jsfiddle.net/R2Frv/1/

<div ng-app="MyAppName">
    <div ng-controller="MyCtrl">
        <p>from Service: {{servGreet}}</p>
        <p>from Provider: {{provGreet}}</p>
    </div>
</div>
<script>
    var myApp = angular.module('MyAppName', []);

    myApp.constant('a', 'Robert');
    myApp.value('b', {name: 'Jones'});

    myApp.service('greetService', function(a,b) {
        this.greeter = 'Hi there, ' + a + ' ' + b.name;
    });

    myApp.provider('greetProvider', function(a) {
        this.firstName = a;
        this.$get = function(b) {
            this.lastName = b.name;
            this.fullName = this.firstName + ' ' + this.lastName;
            return this;
        };
    });

    function MyCtrl($scope, greetService, greetProvider) {
        $scope.servGreet = greetService.greeter;
        $scope.provGreet = greetProvider.fullName;
    }
</script>

Poco in ritardo alla festa. Ma ho pensato che questo sia più utile per chi vorrebbe imparare (o avere chiarezza) sullo sviluppo di servizi personalizzati Angular JS utilizzando metodologie di fabbrica, di servizio e di provider.

Ho trovato questo video che spiega chiaramente le metodologie di fabbrica, di servizio e di fornitore per lo sviluppo di servizi personalizzati AngularJS:

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

Codice sorgente: http://www.techcbt.com/Post/353/Angular-JS-basics/how-to-develop-angularjs-custom-service

Il codice pubblicato qui viene copiato direttamente dalla fonte di cui sopra, a beneficio dei lettori.

Il codice per il servizio personalizzato "factory" è il seguente (che include sia le versioni sync che async insieme al servizio http chiamante):

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

Il codice per la metodologia di "servizio" per i servizi personalizzati (è molto simile a "factory", ma diverso dal punto di vista della sintassi):

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");
		});
	};

}]);

Il codice per la metodologia "provider" per i servizi personalizzati (è necessario, se si desidera sviluppare un servizio che potrebbe essere configurato):

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

Infine l'interfaccia utente che funziona con uno dei servizi di cui sopra:

<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>


Ecco un codice per i broilerplate che ho creato come un modello di codice per la fabbrica di oggetti in AngularjS. Ho usato un Car / CarFactory come esempio per illustrare. Rende semplice il codice di implementazione nel controller.

     <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>

Ecco un esempio più semplice. Sto usando alcune librerie di terze parti che si aspettano un oggetto "Posizione" che esponga latitudine e longitudine, ma tramite proprietà di oggetti diverse. Non volevo hackerare il codice del venditore, quindi ho regolato gli oggetti "Posizione" che stavo passando.

    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

;


Tutte le buone risposte già. Vorrei aggiungere qualche altro punto su Service and Factory . Insieme alla differenza tra servizio / fabbrica. E uno può anche avere domande come:

  1. Dovrei usare il servizio o la fabbrica? Qual è la differenza?
  2. Fanno lo stesso o hanno lo stesso comportamento?

Iniziamo con la differenza tra Service e factory:

  1. Entrambi sono singleton : ogni volta che Angular li trova come una dipendenza per la prima volta, crea una singola istanza di servizio / fabbrica. Una volta creata l'istanza, la stessa istanza viene utilizzata per sempre.

  2. Può essere utilizzato per modellare un oggetto con un comportamento : entrambi possono avere metodi, variabili di stato interne e così via. Anche se il modo in cui scrivi quel codice sarà diverso.

Servizi:

Un servizio è una funzione di costruzione, e Angular lo istanzia da chiamare nuovo yourServiceName(). Questo significa un paio di cose.

  1. Le funzioni e le variabili di istanza saranno proprietà di this.
  2. Non è necessario restituire un valore. Quando chiama Angular new yourServiceName(), riceverà l' thisoggetto con tutte le proprietà che gli hai messo.

Esempio di esempio:

angular.service('MyService', function() {
  this.aServiceVariable = "Ved Prakash"
  this.aServiceMethod = function() {
    return //code
  };
});

Quando Angular inietta questo MyServiceservizio in un controller che dipende da esso, quel controller otterrà un servizio su MyServicecui può chiamare funzioni, ad es. MyService.aServiceMethod ().

Stai attento conthis :

Poiché il servizio costruito è un oggetto, i metodi al suo interno possono fare riferimento a questo quando vengono chiamati:

angular.service('ScoreKeeper', function($http) {
  this.score = 0;

  this.getScore = function() {
    return this.score;
  };

  this.setScore = function(newScore) {
    this.score = newScore;
  };

  this.addOne = function() {
    this.score++;
  };
});

Potresti essere tentato di chiamare ScoreKeeper.setScoreuna catena di promesse, ad esempio se hai inizializzato il punteggio afferrandolo dal server: $http.get('/score').then(ScoreKeeper.setScore).il problema con questo è che ScoreKeeper.setScoreverrà chiamato con il thisvincolo nulle otterrai degli errori. Il modo migliore sarebbe $http.get('/score').then(ScoreKeeper.setScore.bind(ScoreKeeper)). Indipendentemente dal fatto che tu scelga di usarlo nei tuoi metodi di servizio, fai attenzione a come li chiami.

Restituzione di un valore da aService :

A causa del funzionamento dei costruttori JavaScript, se si restituisce un valore complesso (ie, an Object)da una constructorfunzione, il chiamante otterrà tale oggetto anziché questa istanza.

Ciò significa che puoi sostanzialmente copiare e incollare l'esempio di fabbrica dal basso, sostituirlo factorycon service, e funzionerà:

angular.service('MyService', function($http) {
  var api = {};

  api.aServiceMethod= function() {
    return $http.get('/users');
  };
  return api;
});

Quindi, quando Angular costruisce il tuo servizio con il nuovo MyService (), otterrà quell'oggetto API invece dell'istanza MyService.

Questo è il comportamento per qualsiasi valore complesso (oggetti, funzioni) ma non per tipi primitivi.

fabbriche:

Una fabbrica è una semplice vecchia funzione che restituisce un valore. Il valore di ritorno è ciò che viene iniettato in cose che dipendono dalla fabbrica. Un tipico modello di fabbrica in Angolare è restituire un oggetto con funzioni come proprietà, come questo:

angular.factory('MyFactory', function($http) {
  var api = {};

  api.aFactoryMethod= function() {
    return $http.get('/users');
  };

  return api;
});

Il valore iniettato per una dipendenza di fabbrica è il valore di ritorno della fabbrica e non deve essere un oggetto. Potrebbe essere una funzione

Risposte per sopra 1 e 2 domande:

Per la maggior parte, basta usare le fabbriche per tutto. Il loro comportamento è più facile da capire. Non è possibile decidere se restituire un valore o meno e, inoltre, non introdurre errori se si fa la cosa sbagliata.

Mi riferisco ancora a loro come "servizi" quando sto parlando di iniettarli come dipendenze, però.

Il comportamento di Service / Factory è molto simile, e alcune persone diranno che uno va bene. Questo è un po 'vero, ma trovo più semplice seguire il consiglio della guida di stile di John Papa e limitarmi alle fabbriche. **


Il mio chiarimento al riguardo:

Fondamentalmente tutti i tipi menzionati (servizio, fabbrica, fornitore, ecc.) Stanno solo creando e configurando variabili globali (che sono ovviamente globali per l'intera applicazione), proprio come lo erano le variabili globali antiquate.

Mentre le variabili globali non sono raccomandate, l'uso reale di queste variabili globali è quello di fornire un'iniezione di dipendenza , passando la variabile al controller pertinente.

Esistono molti livelli di complicazioni nella creazione dei valori per le "variabili globali":

  1. Costante
    Questo definisce una costante effettiva che non dovrebbe essere modificata durante l'intera applicazione, proprio come le costanti in altre lingue (qualcosa che manca a JavaScript).
  2. Valore
    Questo è un valore o un oggetto modificabile e funge da variabile globale, che può anche essere iniettata quando si creano altri servizi o fabbriche (vedere oltre su questi). Tuttavia, deve essere un " valore letterale ", il che significa che uno deve scrivere il valore effettivo e non può usare alcuna logica di calcolo o programmazione (in altre parole 39 o myText o {prop: "value"} sono OK, ma 2 +2 non lo è).
  3. Fabbrica
    Un valore più generale, che è possibile calcolare immediatamente. Funziona passando una funzione a AngularJS con la logica necessaria per calcolare il valore e AngularJS la esegue, e salva il valore di ritorno nella variabile denominata.
    Si noti che è possibile restituire un oggetto (nel qual caso funzionerà in modo simile a un servizio ) o una funzione (che verrà salvata nella variabile come funzione di callback).
  4. Servizio
    Un servizio è una versione di fabbrica più ridotta che è valida solo quando il valore è un oggetto e consente di scrivere qualsiasi logica direttamente nella funzione (come se fosse un costruttore), oltre a dichiarare e accedere al proprietà dell'oggetto utilizzando la parola chiave this .
  5. Provider
    A differenza di un servizio che è una versione semplificata di fabbrica , un provider è un modo più complesso, ma più flessibile di inizializzare le variabili "globali", con la massima flessibilità essendo l'opzione per impostare valori da app.config.
    Funziona come utilizzando una combinazione di servizi e fornitore , passando per provider di una funzione che ha proprietà dichiarate usando la questa parola chiave, che può essere usato dal app.config.
    Quindi è necessario disporre di una funzione $ .get separata che viene eseguita da AngularJS dopo aver impostato le proprietà di cui sopra tramite il app.configfile, e questa funzione $ .get si comporta esattamente come la fabbrica sopra, in quanto il suo valore di ritorno è usato per inizializzare le variabili "globali".

Dalla mailing list di AngularJS ho ottenuto un thread sorprendente che spiega service vs factory vs provider e il loro uso di injection. Compilando le risposte:

Servizi

Sintassi: module.service( 'serviceName', function );
Risultato: quando si dichiara serviceName come argomento iniettabile, verrà fornita un'istanza della funzione. In altre parole, new FunctionYouPassedToService() .

fabbriche

Sintassi: module.factory( 'factoryName', function );
Risultato: quando si dichiara factoryName come argomento iniettabile, verrà fornito il valore restituito richiamando il riferimento alla funzione passato a module.factory .

provider

Sintassi: module.provider( 'providerName', function );
Risultato: quando si dichiara providerName come argomento iniettabile, verrà fornito (new ProviderFunction()).$get() . La funzione di costruzione viene istanziata prima che venga chiamato il metodo $ get - ProviderFunction è il riferimento alla funzione passato a module.provider.

I provider hanno il vantaggio di poter essere configurati durante la fase di configurazione del modulo.

Vedi here per il codice fornito.

Ecco un'ulteriore grande spiegazione di Misko:

provide.value('a', 123);

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

In questo caso l'iniettore restituisce semplicemente il valore così com'è. Ma cosa succede se si desidera calcolare il valore? Quindi usa una fabbrica

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

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

Quindi la factory è una funzione che è responsabile della creazione del valore. Si noti che la funzione di fabbrica può richiedere altre dipendenze.

Ma cosa succede se vuoi essere più OO e avere una classe chiamata Greeter?

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

Quindi per istanziare dovresti scrivere

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

Quindi potremmo chiedere "greeter" in controller come questo

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

Ma è troppo verboso. Un modo più breve per scrivere questo sarebbe provider.service('greeter', Greeter);

Ma cosa succede se volessimo configurare la classe Greeter prima dell'iniezione? Quindi potremmo scrivere

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);
  };
});

Quindi possiamo fare questo:

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

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

Come nota a margine, il service , la factory e il value sono tutti derivati ​​dal fornitore.

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;
  });
};

A seconda della memoria, i controller vengono istanziati solo quando sono necessari e scartati quando non lo sono. Per questo motivo, ogni volta che si cambia rotta o si ricarica una pagina, Angular pulisce il controller corrente. I servizi forniscono tuttavia un mezzo per mantenere i dati in giro per tutta la durata di un'applicazione mentre possono essere utilizzati anche tra diversi controller in modo coerente.

Angular ci fornisce tre modi per creare e registrare il nostro servizio.

1) fabbrica

2) Servizio

3) Provider

Fabbrica : una fabbrica è una semplice funzione che consente di aggiungere una certa logica prima di creare l'oggetto. Restituisce l'oggetto creato.

È solo una raccolta di funzioni come una classe. Quindi, può essere istanziato in diversi controller quando lo si utilizza con la funzione di costruzione.

Servizio : un servizio è una funzione di costruzione che crea l'oggetto utilizzando una nuova parola chiave. È possibile aggiungere proprietà e funzioni a un oggetto servizio utilizzando questa parola chiave. A differenza della fabbrica, non restituisce nulla.

È un oggetto singleton. Usalo quando hai bisogno di condividere un singolo oggetto attraverso l'applicazione. Ad esempio, i dettagli dell'utente autenticato.

Provider : un provider viene utilizzato per creare un oggetto di servizio configurabile. Restituisce valore usando la funzione $ get ().

Quando è necessario fornire una configurazione basata su modulo per il proprio oggetto di servizio prima di renderlo disponibile.

Esegui il seguente codice e vedi l'output.

<!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>


Dopo aver letto tutti questi post ha creato più confusione per me .. Ma ancora tutto è degno di informazioni .. finalmente ho trovato la seguente tabella che fornirà informazioni con un semplice confronto

  • L'iniettore utilizza le ricette per creare due tipi di oggetti: servizi e oggetti per scopi speciali
  • Esistono cinque tipi di ricetta che definiscono come creare oggetti: Valore, Fabbrica, Servizio, Fornitore e Costante.
  • La fabbrica e il servizio sono le ricette più utilizzate. L'unica differenza tra loro è che la ricetta del servizio funziona meglio per oggetti di un tipo personalizzato, mentre la Factory può produrre primitive e funzioni JavaScript.
  • La ricetta del provider è il tipo di ricetta principale e tutti gli altri sono solo zucchero sintattico.
  • Il fornitore è il tipo di ricetta più complesso. Non ne hai bisogno a meno che non stai costruendo un pezzo di codice riutilizzabile che richiede una configurazione globale.
  • Tutti gli oggetti speciali ad eccezione del controller sono definiti tramite ricette di fabbrica.

E per i principianti capire: - Questo potrebbe non correggere il caso d'uso ma in alto questo è ciò che serve per questi tre.

  1. Se si desidera utilizzare nel modulo angolare, la funzione di configurazione dovrebbe essere creata come fornitore

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

  1. La chiamata Ajax o le integrazioni di terze parti devono essere di servizio .
  2. Per le manipolazioni dei dati, crealo come fabbrica

Per gli scenari di base, fabbrica e servizio si comportano allo stesso modo.


Discutiamo i tre modi di gestire la logica di business in AngularJS in modo semplice: ( Ispirato al corso Coursera AngularJS di Yaakov )

SERVIZIO :

Sintassi:

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>

Caratteristiche del servizio:

  1. Istanziato in modo laziale : se non viene iniettato, non verrà mai istanziato. Quindi per usarlo dovrà iniettarlo in un modulo.
  2. Singleton : se iniettato su più moduli, tutti avranno accesso a una sola istanza particolare. Questo è il motivo per cui è molto comodo condividere i dati tra diversi controller.

FABBRICA

Per prima cosa diamo un'occhiata alla sintassi:

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;
}

Ora usando i due precedenti nel controller:

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

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

Caratteristiche di fabbrica:

  1. Segue lo schema di progettazione della fabbrica. La fabbrica è un luogo centrale che produce nuovi oggetti o funzioni.
  2. Non solo produce servizi singleton, ma personalizzabili.
  3. Il .service()metodo è una fabbrica che produce sempre lo stesso tipo di servizio, che è un singleton e senza alcun modo semplice per configurare il suo comportamento. Questo .service()metodo viene solitamente utilizzato come scorciatoia per qualcosa che non richiede alcuna configurazione.

PROVIDER

Diamo prima un'occhiata alla sintassi:

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;
  };
}

}

Funzionalità del Provider:

  1. Il fornitore è il metodo più flessibile per creare servizi in Angular.
  2. Non solo possiamo creare una fabbrica che sia configurabile dinamicamente, ma al momento di utilizzare la fabbrica, con il metodo del fornitore, potremmo configurare la fabbrica una volta sola all'avvio della nostra intera applicazione.
  3. La fabbrica può quindi essere utilizzata in tutta l'applicazione con impostazioni personalizzate. In altre parole, possiamo configurare questo factory prima che l'applicazione abbia inizio. Infatti nella documentazione angolare viene menzionato che il metodo provider è ciò che viene effettivamente eseguito dietro le quinte quando configuriamo i nostri servizi con uno .serviceo più .factorymetodi.
  4. La $getè una funzione direttamente collegata all'istanza del provider. Quella funzione è una funzione di fabbrica . In altre parole, è proprio come quello che usiamo per fornire al .factorymetodo. In quella funzione, creiamo il nostro servizio. Questa $getproprietà, è una funzione, è ciò che rende il provider un fornitore . AngularJS si aspetta che il provider abbia una proprietà $ get il cui valore è una funzione che Angular considera come una funzione di fabbrica. Ma ciò che rende questa installazione di tutto il provider molto speciale, è il fatto che possiamo fornire qualche configoggetto all'interno del fornitore di servizi e che di solito viene fornito con valori predefiniti che possiamo sovrascrivere in seguito nel passaggio, dove possiamo configurare l'intera applicazione.

Comprensione di AngularJS Factory, Service e Provider

Tutti questi sono usati per condividere oggetti singleton riutilizzabili. Aiuta a condividere il codice riutilizzabile attraverso la tua app / vari componenti / moduli.

Dal Service/Factory :

  • Istanziata in modo semplice - Angolare crea un'istanza di servizio / fabbrica solo quando un componente dell'applicazione dipende da esso.
  • Singoli - Ogni componente che dipende da un servizio ottiene un riferimento alla singola istanza generata dalla fabbrica del servizio.

Fabbrica

Una factory è una funzione in cui è possibile manipolare / aggiungere la logica prima di creare un oggetto, quindi viene restituito l'oggetto appena creato.

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

Può essere solo una raccolta di funzioni come una classe. Quindi, può essere istanziato in diversi controller quando lo si sta iniettando all'interno delle funzioni del controller / fabbrica / direttiva. Viene creato solo una volta per app.

Servizio

Semplicemente guardando i servizi pensate al prototipo dell'array. Un servizio è una funzione che crea un'istanza di un nuovo oggetto utilizzando la parola chiave 'nuova'. È possibile aggiungere proprietà e funzioni a un oggetto servizio utilizzando la parola chiave this . A differenza di una factory, non restituisce nulla (restituisce un oggetto che contiene metodi / proprietà).

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

uso

Usalo quando hai bisogno di condividere un singolo oggetto in tutta l'applicazione. Ad esempio, dettagli utente autenticati, metodi / dati condivisibili, funzioni di utilità, ecc.

Provider

Un provider viene utilizzato per creare un oggetto di servizio configurabile. È possibile configurare le impostazioni del servizio dalla funzione di configurazione. Restituisce un valore usando la $get()funzione. La $getfunzione viene eseguita nella fase di esecuzione in angolare.

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

Quando è necessario fornire una configurazione basata su modulo per il proprio oggetto di servizio prima di renderlo disponibile, ad es. si supponga di voler impostare l'URL dell'API in base al proprio ambiente come dev, stageoprod

NOTA

Solo il fornitore sarà disponibile nella fase di configurazione angolare, mentre il servizio e la fabbrica non lo sono.

Spero che questo abbia chiarito le tue conoscenze su Factory, Service e Provider .


Per me il modo migliore e più semplice per capire la differenza è:

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

Come AngularJS istanzia particolari componenti (semplificati):

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

// factory
var angularFactory = factory(injection);

Quindi, per il servizio, ciò che diventa il componente AngularJS è l'istanza dell'oggetto della classe che è rappresentata dalla funzione di dichiarazione del servizio. Per la fabbrica, è il risultato restituito dalla funzione di dichiarazione di fabbrica. La fabbrica può comportarsi come il servizio:

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

Il modo più semplice di pensare è il seguente:

  • Il servizio è un'istanza dell'oggetto singleton. Utilizzare i servizi se si desidera fornire un oggetto singleton per il proprio codice.
  • La fabbrica è una classe. Usa le fabbriche se vuoi fornire classi personalizzate per il tuo codice (non può essere fatto con i servizi perché sono già istanziati).

L'esempio di "classe" di fabbrica è fornito nei commenti in giro, così come la differenza tra i fornitori.


AngularJS memorizza il valore e lo confronta con un valore precedente. Questo è un semplice controllo sporco. Se c'è un cambiamento nel valore, allora spara l'evento change.

Il metodo $apply() , che è quello che chiami quando stai passando da un mondo non-AngularJS in un mondo AngularJS, chiama $digest() . Un digest è semplicemente un vecchio controllo sporco. Funziona su tutti i browser ed è totalmente prevedibile.

Per contrastare il dirty-checking (AngularJS) e cambiare i listener ( KnockoutJS e Backbone.js ): mentre il dirty-checking può sembrare semplice, e persino inefficiente (lo affronterò più avanti), risulta che è semanticamente corretto tutto il tempo, mentre i cambia ascoltatori hanno molti casi angusti e hanno bisogno di cose come il rilevamento delle dipendenze per renderlo più semanticamente corretto. Il rilevamento delle dipendenze KnockoutJS è una funzionalità intelligente per un problema che AngularJS non ha.

Problemi con gli ascoltatori di cambiamenti:

  • La sintassi è atroce, poiché i browser non la supportano in modo nativo. Sì, ci sono proxy, ma non sono semanticamente corretti in tutti i casi, e ovviamente non ci sono proxy sui vecchi browser. La linea di fondo è che il dirty-checking ti permette di fare POJO , mentre KnockoutJS e Backbone.js ti costringono ad ereditare dalle loro classi e ad accedere ai tuoi dati tramite gli accessor.
  • Cambia coalescenza. Supponi di avere una serie di elementi. Supponiamo che tu voglia aggiungere elementi in un array, mentre esegui il ciclo per aggiungere, ogni volta che aggiungi attivi eventi in modifica, che sta rendendo l'interfaccia utente. Questo è molto negativo per le prestazioni. Quello che vuoi è aggiornare l'interfaccia utente solo una volta, alla fine. Gli eventi di modifica sono troppo chiari.
  • Cambiare gli ascoltatori sparare immediatamente su un setter, che è un problema, dal momento che il listener di modifiche può ulteriormente modificare i dati, il che genera più eventi di cambiamento. Questo è un problema poiché sul tuo stack potresti avere diversi eventi di cambiamento che accadono contemporaneamente. Supponiamo di avere due array che devono essere tenuti sincronizzati per qualsiasi motivo. È possibile solo aggiungere a uno o l'altro, ma ogni volta che si aggiunge si attiva un evento di modifica, che ora ha una visione incoerente del mondo. Questo è un problema molto simile al thread lock, che JavaScript evita dal momento che ogni callback viene eseguito esclusivamente e fino al completamento. Gli eventi di cambiamento rompono questo dato che i setter possono avere conseguenze di vasta portata che non sono intese e non ovvie, il che crea di nuovo il problema del filo. Si scopre che ciò che si vuole fare è ritardare l'esecuzione del listener e garantire che venga eseguito un solo listener alla volta, quindi qualsiasi codice è libero di cambiare i dati e sa che nessun altro codice viene eseguito mentre lo fa .

Che dire delle prestazioni?

Quindi può sembrare che siamo lenti, dal momento che il controllo sporco è inefficiente. Qui è dove dobbiamo guardare i numeri reali piuttosto che avere solo argomenti teorici, ma prima definiamo alcuni vincoli.

Gli umani sono:

  • Lento - Qualsiasi cosa più veloce di 50 ms è impercettibile per gli esseri umani e quindi può essere considerata come "istantanea".

  • Limitato - Non puoi mostrare più di circa 2000 informazioni su un essere umano su una singola pagina. Qualunque cosa in più è un'interfaccia utente davvero brutta, e gli umani non possono elaborarlo comunque.

Quindi la vera domanda è questa: quanti confronti puoi fare su un browser in 50 ms? Questa è una domanda difficile a cui rispondere quando entrano in gioco molti fattori, ma qui c'è un caso di test: http://jsperf.com/angularjs-digest/6 che crea 10.000 watcher. Su un browser moderno questo richiede poco meno di 6 ms. Su Internet Explorer 8 ci vogliono circa 40 ms. Come puoi vedere, questo non è un problema nemmeno con i browser lenti in questi giorni. C'è un avvertimento: i confronti devono essere semplici per rientrare nel limite di tempo ... Sfortunatamente è troppo facile aggiungere un confronto lento in AngularJS, quindi è facile creare applicazioni lente quando non si sa cosa sta facendo. Ma speriamo di avere una risposta fornendo un modulo di strumentazione, che ti mostri quali sono i confronti lenti.

Risulta che i videogiochi e le GPU utilizzano l'approccio di controllo sporco, in particolare perché è coerente. Fintanto che superano la frequenza di aggiornamento del monitor (in genere 50-60 Hz, o ogni 16.6-20 ms), qualsiasi prestazione su quella è una perdita, quindi è meglio disegnare più cose, piuttosto che ottenere un FPS più alto.





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