Domanda AngularJS: Service vs provider vs factory


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


3163
2018-03-27 17:59


origine


risposte:


Dalla mailing list di AngularJS che ho ricevuto un thread sorprendente ciò spiega il servizio rispetto al fornitore di fabbrica e al loro utilizzo di iniezione. Compilando le risposte:

Servizi

Sintassi: module.service( 'serviceName', function ); 
Risultato: quando si dichiara serviceName come argomento iniettabile ti 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 che verrà fornito il valore che viene restituito invocando il riferimento alla funzione passato a module.factory.

provider

Sintassi: module.provider( 'providerName', function ); 
Risultato: quando si dichiara providerName come argomento iniettabile ti 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.

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

Così 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 se volessimo configurare il Greeter classe 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, service, factory, e 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;
  });
};

2800
2017-07-30 10:20



JS Fiddle Demo

Esempio "Ciao mondo" con factory / service / provider:

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

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

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

    this.name = 'Default';

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

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

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

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


796
2018-05-15 15:53



TL; DR 

1) Quando usi un Fabbrica si crea un oggetto, si aggiungono proprietà, quindi si restituisce lo stesso oggetto. Quando si passa questo stabilimento al controller, tali proprietà sull'oggetto saranno ora disponibili in quel controller attraverso la fabbrica.

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) Quando stai usando Servizio, AngularJS lo istanzia dietro le quinte con la "nuova" parola chiave. Per questo motivo, aggiungi proprietà a "this" e il servizio restituirà "this". Quando si passa il servizio nel controller, tali proprietà su "this" saranno ora disponibili su quel controller tramite il servizio.

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

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



3)  provider sono l'unico servizio che puoi passare alla tua funzione .config (). Utilizzare un provider quando si desidera fornire la configurazione a livello di modulo per il proprio oggetto di servizio prima di renderlo disponibile.

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

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

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



Non TL; DR

1) fabbrica 
Le fabbriche sono il modo più popolare per creare e configurare un servizio. Non c'è davvero molto di più di quello che TL, DR ha detto. Devi solo creare un oggetto, aggiungere proprietà ad esso, quindi restituire lo stesso oggetto. Quindi, quando si passa la fabbrica nel controller, tali proprietà sull'oggetto saranno ora disponibili in quel controller attraverso la fabbrica. Un esempio più ampio è qui sotto.

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

Ora qualsiasi proprietà che attribuiamo al "servizio" sarà a nostra disposizione quando passeremo "myFactory" nel nostro controller.

Ora aggiungiamo alcune variabili 'private' alla nostra funzione di callback. Questi non saranno direttamente accessibili dal controller, ma alla fine creeremo alcuni metodi getter / setter su 'service' per poter modificare queste variabili 'private' quando necessario.

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

Qui noterai che non stiamo associando quelle variabili / funzioni a 'servizio'. Li stiamo semplicemente creando per utilizzarli o modificarli in seguito.

  • baseUrl è l'URL di base richiesto dall'API di iTunes
  • _artist è l'artista che desideriamo cercare
  • _finalUrl è l'URL finale e completo a cui faremo la chiamata ad iTunes
  • makeUrl è una funzione che creerà e restituirà il nostro URL amichevole di iTunes.

Ora che sono disponibili le nostre variabili helper / private e la funzione, aggiungiamo alcune proprietà all'oggetto 'service'. Qualsiasi cosa mettiamo sul "servizio" può essere direttamente utilizzata all'interno di qualsiasi controller in cui passiamo "myFactory".

Creeremo metodi setArtist e getArtist che semplicemente restituiscono o impostano l'artista. Stiamo anche creando un metodo che chiamerà l'API di iTunes con il nostro URL creato. Questo metodo restituirà una promessa che si realizzerà non appena i dati torneranno dall'API di iTunes. Se non hai avuto molta esperienza nell'usare promesse in AngularJS, consiglio vivamente di fare un tuffo profondo su di loro.

Sotto setArtist accetta un artista e ti permette di impostare l'artista. getArtist restituisce l'artista. callItunes prima chiama makeUrl () per costruire l'URL che useremo con la nostra richiesta $ http. Quindi imposta un oggetto promessa, effettua una richiesta $ http con il nostro URL finale, quindi perché $ http restituisce una promessa, siamo in grado di chiamare .success o .error dopo la nostra richiesta. Quindi risolviamo la nostra promessa con i dati di iTunes, oppure la rifiutiamo con un messaggio che dice "C'era un errore".

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

Ora la nostra fabbrica è completa. Ora siamo in grado di iniettare "myFactory" in qualsiasi controller e potremo quindi chiamare i nostri metodi che abbiamo allegato al nostro oggetto di servizio (setArtist, getArtist e 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);
      })
  }
});

Nel controller sopra ci stiamo iniettando nel servizio 'myFactory'. Quindi impostiamo le proprietà sul nostro oggetto $ scope con i dati di "myFactory". L'unico codice difficile sopra è se non hai mai affrontato le promesse prima. Poiché callItunes sta restituendo una promessa, siamo in grado di utilizzare il metodo .then () e di impostare $ scope.data.artistData una volta che la nostra promessa è stata soddisfatta con i dati di iTunes. Noterai che il nostro controller è molto "sottile" (questa è una buona pratica di codifica). Tutta la nostra logica e i dati persistenti si trovano nel nostro servizio, non nel nostro controller.

2) Servizio 
Forse la cosa più importante da sapere quando si ha a che fare con la creazione di un servizio è quella di creare un'istanza con la parola chiave "nuova". Per voi guru JavaScript questo dovrebbe darvi un grande suggerimento sulla natura del codice. Per quelli di voi con uno sfondo limitato in JavaScript o per coloro che non conoscono troppo bene la parola chiave "nuova", esaminiamo alcuni concetti fondamentali di JavaScript che alla fine ci aiuteranno a capire la natura di un servizio.

Per vedere veramente i cambiamenti che si verificano quando invochi una funzione con la parola chiave 'nuova', creiamo una funzione e la invochiamo con la 'nuova' parola chiave, quindi mostriamo cosa fa l'interprete quando vede la parola chiave 'nuova'. I risultati finali saranno entrambi uguali.

Per prima cosa creiamo il nostro Costruttore.

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

Questa è una tipica funzione di costruzione JavaScript. Ora ogni volta che invochiamo la funzione Persona usando la "nuova" parola chiave, "questo" sarà associato all'oggetto appena creato.

Ora aggiungiamo un metodo al prototipo della nostra persona in modo che sia disponibile su ogni istanza della "classe" della nostra persona.

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

Ora, poiché inseriamo la funzione sayName sul prototipo, ogni istanza di Person sarà in grado di chiamare la funzione sayName per avvisare il nome di tale istanza.

Ora che abbiamo la nostra funzione di costruzione Person e la nostra funzione sayName sul suo prototipo, creiamo effettivamente un'istanza di Persona, quindi chiamiamo la funzione sayName.

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

Quindi, tutto il codice per creare un costruttore Person, aggiungere una funzione al suo prototipo, creare un'istanza Persona e quindi chiamare la funzione sul suo prototipo appare così.

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’

Ora vediamo cosa succede realmente quando usi la "nuova" parola chiave in JavaScript. La prima cosa che dovresti notare è che dopo aver usato 'new' nel nostro esempio, siamo in grado di chiamare un metodo (sayName) su 'tyler' proprio come se fosse un oggetto - è perché lo è. Quindi, per prima cosa, sappiamo che il nostro costruttore di Person sta restituendo un oggetto, se possiamo vederlo nel codice oppure no. In secondo luogo, sappiamo che poiché la nostra funzione sayName si trova sul prototipo e non direttamente sull'istanza Person, l'oggetto che la funzione Persona sta restituendo deve delegare al suo prototipo su ricerche fallite. In termini più semplici, quando chiamiamo tyler.sayName () l'interprete dice "OK, vado a cercare sull'oggetto 'tyler' che abbiamo appena creato, individuare la funzione sayName, quindi chiamarla. Aspetta un attimo, non lo vedo qui - tutto quello che vedo è il nome e l'età, fammi controllare il prototipo. Sì, sembra che sia sul prototipo, lascia che lo chiami ".

Di seguito è riportato il codice per come puoi pensare a ciò che la parola chiave "nuova" sta effettivamente facendo in JavaScript. È fondamentalmente un esempio di codice del paragrafo precedente. Ho inserito la "vista dell'interprete" o il modo in cui l'interprete vede il codice all'interno delle note.

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

Ora avendo questa conoscenza di ciò che la "nuova" parola chiave fa davvero in JavaScript, la creazione di un servizio in AngularJS dovrebbe essere più facile da capire.

La cosa più importante da capire quando si crea un servizio è sapere che i servizi vengono istanziati con la parola chiave 'nuova'. Combinando questa conoscenza con i nostri esempi sopra, ora dovresti riconoscere che allegerai le tue proprietà e i tuoi metodi direttamente a "questo" che verrà poi restituito dal Servizio stesso. Diamo un'occhiata a questo in azione.

A differenza di ciò che originariamente avevamo fatto con l'esempio Factory, non abbiamo bisogno di creare un oggetto, quindi restituire quell'oggetto perché, come accennato molte volte prima, abbiamo usato la parola chiave 'new' in modo che l'interprete crei quell'oggetto, lo faccia delegare a è un prototipo, quindi restituiscilo per noi senza che noi dobbiamo fare il lavoro.

Per prima cosa, creiamo la nostra funzione "privata" e di aiuto. Questo dovrebbe sembrare molto familiare dato che abbiamo fatto esattamente la stessa cosa con la nostra fabbrica. Non spiegherò cosa fa ogni riga qui perché l'ho fatto nell'esempio di fabbrica, se sei confuso, rileggi l'esempio di fabbrica.

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

Ora, allegheremo tutti i nostri metodi che saranno disponibili nel nostro controller per "questo".

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

});

Ora, proprio come nella nostra fabbrica, setArtist, getArtist e callItunes saranno disponibili in qualsiasi controller in cui passiamo myService. Ecco il controller myService (che è quasi esattamente lo stesso del nostro controller di fabbrica).

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

Come ho detto prima, una volta compreso veramente cosa fa 'new', i servizi sono quasi identici alle fabbriche di AngularJS.

3) Provider

La cosa più importante da ricordare sui provider è che sono l'unico servizio che è possibile trasferire nella parte app.config dell'applicazione. Questo è di grande importanza se hai bisogno di modificare parte del tuo oggetto di servizio prima che sia disponibile ovunque nella tua applicazione. Sebbene siano molto simili a Servizi / Fabbriche, ci sono alcune differenze di cui discuteremo.

Per prima cosa impostiamo il nostro Provider in un modo simile che abbiamo fatto con il nostro servizio e la fabbrica. Le variabili sottostanti sono la nostra funzione 'privata' e di supporto.

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

* Di nuovo, se qualche parte del codice sopra è confusa, controlla la sezione Factory dove spiego cosa fa tutti i dettagli maggiori.

Puoi pensare ai Provider come aventi tre sezioni. La prima sezione è le variabili / funzioni 'private' che verranno modificate / impostate in un secondo momento (mostrato sopra). La seconda sezione è le variabili / funzioni che saranno disponibili nella tua funzione app.config e sono quindi disponibili per alterare prima che siano disponibili altrove (anche mostrato sopra). È importante notare che queste variabili devono essere associate alla parola chiave "this". Nel nostro esempio, solo "cosaFromConfig" sarà disponibile per modificare in app.config. La terza sezione (mostrata sotto) è tutte le variabili / funzioni che saranno disponibili nel controller quando si passa il servizio 'myProvider' in quel controller specifico.

Quando si crea un servizio con il provider, le sole proprietà / metodi che saranno disponibili nel controller sono quelle proprietà / metodi restituiti dalla funzione $ get (). Il codice qui sotto mette $ get su 'this' (che sappiamo sarà eventualmente restituito da tale funzione). Ora, la funzione $ get restituisce tutti i metodi / proprietà che vogliamo siano disponibili nel controller. Ecco un esempio di codice.

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

Ora il codice Provider completo appare così

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

Ora, proprio come nella nostra fabbrica e nel nostro servizio, setArtist, getArtist e callItunes saranno disponibili in qualsiasi controller in cui passiamo myProvider. Ecco il controller myProvider (che è quasi esattamente lo stesso del nostro controller di fabbrica / servizio).

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

Come accennato in precedenza, l'intero punto di creazione di un servizio con Provider è di essere in grado di modificare alcune variabili tramite la funzione app.config prima che l'oggetto finale venga passato al resto dell'applicazione. Vediamo un esempio di questo.

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

Ora puoi vedere come 'thingFromConfig' è una stringa vuota nel nostro provider, ma quando questo appare nel DOM, sarà 'Questa frase è stata impostata ...'.


618
2017-12-24 13:15



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

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

Il più dettagliato, ma anche il più completo è un Provider   ricetta. Il rimanenti quattro tipi di ricetta: valore, fabbrica, servizio e   Costante - sono solo zucchero sintattico sulla cima di una ricetta del fornitore.

  • Il Ricetta del valore è il caso più semplice, in cui istanziate il servizio da soli e fornite il valore istanziato all'iniettore.
  • Il Ricetta di fabbrica fornisce all'iniettore una funzione di fabbrica che chiama quando è necessario istanziare il servizio. Quando chiamato, il funzione di fabbrica 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
  • Il Ricetta di servizio è quasi la stessa della ricetta di fabbrica, ma qui l'Injector invoca a costruttore con il nuovo operatore invece di una funzione di fabbrica.
  • Il Ricetta del fornitore di solito eccessivo. 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 effettuata prima del   l'applicazione inizia. Questo di solito è interessante solo per riutilizzabile   servizi il cui comportamento potrebbe dover variare leggermente   applicazioni.


506
2018-02-01 12:58



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.

Da documenti Servizio / Fabbrica:

  • Istanziato pigramente - Angular crea un'istanza di servizio / fabbrica solo quando un componente dell'applicazione dipende da esso.
  • Singletons - Ogni componente   dipende da un servizio ottiene un riferimento alla singola istanza   generato dalla fabbrica di servizi.

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 thisparola chiave. 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 il $get() funzione. Il $get la funzione viene eseguita in 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. supponi di voler impostare l'URL dell'API in base al tuo ambiente come dev, stage o prod

NOTA 

Solo il fornitore sarà disponibile in fase di configurazione di angolare, mentre   servizio e fabbrica no.

Spero che questo abbia chiarito la tua comprensione Fabbrica, servizio e fornitore.


221
2017-11-14 06:25



Per me, la rivelazione è arrivata quando ho capito che tutti funzionano allo stesso modo: eseguendo qualcosa una volta, memorizzando il valore che ottengono, e poi tossendo quello stesso valore memorizzato quando referenziato attraverso iniezione di dipendenza.

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 proviene da prima ottenendo un'istanza da newing fne quindi eseguendo a $get metodo 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 usiamo this nei servizi e definire a this.$get nei fornitori.


190
2017-07-22 11:39



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, Servizio non è 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;})

Fornisce AngularJS 'factory (' serviceName ', fnFactory)' metodo che accetta due parametri, serviceName e una funzione JavaScript. Angular crea un'istanza del servizio richiamando 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 utilizzare una funzione di fabbrica che restituisce un'istanza di servizio. serviceInstance = fnFactory ();

Servizio utilizzare 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 ();

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


133
2017-11-19 13:36



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 provider in tutti loro. Così:

enter image description here

Ecco l'articolo di questa immagine tratta da:

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


79
2017-08-02 05:37



Fabbrica

Se assegni ad AngularJS una funzione, AngularJS effettuerà il caching e inserirà il valore restituito quando viene richiesto il factory.

Esempio:

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

Servizio

Dite ad AngularJS una funzione, AngularJS chiamerà nuovo per istanziarlo. È l'istanza creata da AngularJS che verrà memorizzata nella cache e iniettata quando viene richiesto il servizio. Da nuovo è stato utilizzato per istanziare il servizio, la parola chiave Questo è valido e si riferisce all'istanza.

Esempio:

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

Provider

Dite ad AngularJS una funzione, e AngularJS la chiamerà $get funzione. È il valore di ritorno dal $get funzione che verrà memorizzata nella cache e iniettata quando viene richiesto il servizio.

I provider ti consentono di configurare il provider prima AngularJS chiama il $get metodo per ottenere l'iniettabile.

Esempio:

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

Uso (come iniettabile in un controller)

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

Utilizzo (prima configurazione del provider $get è chiamato a creare l'iniettabile)

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

62
2018-05-19 19:53



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" AngularJS (ad esempio, myApp.constant('a', 'Robert');), è possibile iniettarlo in servizi, fabbriche e fornitori.

Ma se dichiari un "valore" AngularJS (ad esempio., myApp.value('b', {name: 'Jones'});), è possibile iniettarlo in servizi e fabbriche, ma NON nella funzione di creazione del provider. Tuttavia, è possibile iniettarlo nel $get funzione 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>

54
2017-10-09 03:43



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

Servizio AngularJS: è usato per condividere le funzioni di utilità con il riferimento di 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 i nomi delle funzioni come proprietà con Questo oggetto.

Fabbrica AngularJS: 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, ma Provider fornisce l'output della sua funzione $ get.

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


43
2018-04-30 11:20