Frage AngularJS: Service versus Provider vs factory


Was sind die Unterschiede zwischen a Service, Provider und Factory in AngularJS?


3163
2018-03-27 17:59


Ursprung


Antworten:


Von der AngularJS-Mailingliste habe ich ein toller Thread das erklärt service vs factory vs. provider und deren injektion. Die Antworten zusammenstellen:

Dienstleistungen

Syntax: module.service( 'serviceName', function ); 
Ergebnis: Wenn serviceName als injizierbares Argument deklariert wird Sie erhalten eine Instanz der Funktion. Mit anderen Worten  new FunctionYouPassedToService().

Fabriken

Syntax: module.factory( 'factoryName', function ); 
Ergebnis: Wenn factoryName als injizierbares Argument deklariert wird, wird Ihnen Folgendes mitgeteilt Der Wert, der zurückgegeben wird, indem die Funktionsreferenz aufgerufen wird, die an module.factory übergeben wurde.

Anbieter

Syntax: module.provider( 'providerName', function ); 
Ergebnis: Wenn providerName als injizierbares Argument deklariert wird Sie werden mit versorgt werden  (new ProviderFunction()).$get(). Die Konstruktorfunktion wird instanziiert, bevor die $ get-Methode aufgerufen wird - ProviderFunction ist die Funktionsreferenz, die an module.provider übergeben wird.

Provider haben den Vorteil, dass sie während der Modulkonfigurationsphase konfiguriert werden können.

Sehen Hier für den bereitgestellten Code.

Hier ist eine große weitere Erklärung von Misko:

provide.value('a', 123);

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

In diesem Fall gibt der Injektor einfach den Wert wie er ist zurück. Aber was, wenn Sie den Wert berechnen möchten? Dann benutze eine Fabrik

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

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

Damit factory ist eine Funktion, die für die Erstellung des Wertes verantwortlich ist. Beachten Sie, dass die Factory-Funktion nach anderen Abhängigkeiten fragen kann.

Aber was, wenn du mehr OO sein und eine Klasse namens Greeter haben willst?

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

Dann müssten Sie schreiben, um zu instantiieren

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

Dann könnten wir in Controller so 'Greeter' fragen

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

Aber das ist viel zu wortwörtlich. Ein kürzerer Weg dies zu schreiben wäre provider.service('greeter', Greeter);

Aber was, wenn wir das konfigurieren wollten Greeter Klasse vor der Injektion? Dann könnten wir schreiben

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

Dann können wir das machen:

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

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

Als Anmerkung, service, factory, und value sind alle vom Anbieter abgeleitet.

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

"Hallo Welt" -Beispiel mit 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) Wenn Sie ein Fabrik Sie erstellen ein Objekt, fügen Eigenschaften hinzu und geben dasselbe Objekt zurück. Wenn Sie diese Factory an Ihren Controller übergeben, sind diese Eigenschaften für das Objekt jetzt in diesem Controller über Ihre Factory verfügbar.

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) Wenn Sie verwenden Bedienung, AngularJS instanziiert es hinter den Kulissen mit dem Schlüsselwort 'new'. Aus diesem Grund fügen Sie 'this' Eigenschaften hinzu, und der Dienst gibt 'this' zurück. Wenn Sie den Service an Ihren Controller übergeben, sind diese Eigenschaften für diesen Service nun über diesen Service auf diesem Controller verfügbar.

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

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



3)  Anbieter sind die einzigen Dienste, die Sie an Ihre .config () - Funktion übergeben können. Verwenden Sie einen Anbieter, wenn Sie für Ihr Serviceobjekt eine modulweite Konfiguration bereitstellen möchten, bevor Sie sie bereitstellen.

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



Nicht TL; DR

1) Fabrik 
Fabriken sind die beliebteste Methode zum Erstellen und Konfigurieren eines Service. Es gibt wirklich nicht viel mehr als das, was die TL; DR sagte. Sie erstellen einfach ein Objekt, fügen Eigenschaften hinzu und geben dann dasselbe Objekt zurück. Wenn Sie die Fabrik dann an Ihren Controller übergeben, sind diese Eigenschaften für das Objekt jetzt in diesem Controller über Ihre Fabrik verfügbar. Ein ausführlicheres Beispiel ist unten.

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

Nun stehen uns alle Eigenschaften zur Verfügung, die wir an "Service" vergeben, wenn wir "myFactory" in unseren Controller eingeben.

Nun fügen wir unserer Callback-Funktion einige 'private' Variablen hinzu. Diese werden vom Controller nicht direkt zugänglich sein, aber wir werden eventuell einige Getter / Setter-Methoden für "Service" einrichten, um diese "privaten" Variablen bei Bedarf ändern zu können.

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

Hier werden Sie feststellen, dass wir diese Variablen / Funktionen nicht an "Service" anhängen. Wir erstellen sie einfach, um sie später zu verwenden oder zu ändern.

  • baseUrl ist die Basis-URL, die für die iTunes-API erforderlich ist
  • _artist ist der Künstler, den wir suchen möchten
  • _finalUrl ist die endgültige und vollständig erstellte URL, zu der wir den Anruf bei iTunes tätigen werden
  • makeUrl ist eine Funktion, die unsere iTunes-freundliche URL erstellt und zurückgibt.

Jetzt, da unsere help / private Variablen und Funktionen vorhanden sind, fügen wir dem Objekt 'service' einige Eigenschaften hinzu. Was immer wir "Service" nennen, kann direkt in jedem Controller verwendet werden, an den wir "myFactory" übergeben.

Wir werden die Methoden setArtist und getArtist erstellen, die den Künstler einfach zurückgeben oder setzen. Wir werden auch eine Methode erstellen, die die iTunes API mit unserer erstellten URL aufruft. Diese Methode liefert ein Versprechen, das erfüllt wird, sobald die Daten von der iTunes-API zurückgegeben wurden. Wenn Sie nicht viel Erfahrung mit Versprechungen in AngularJS gemacht haben, empfehle ich dringend, einen tiefen Tauchgang an ihnen zu machen.

Unten setArtist akzeptiert einen Künstler und erlaubt Ihnen, den Künstler einzustellen. getArtist gibt den Künstler zurück. AnrufItunes ruft zuerst makeUrl () auf, um die URL zu erstellen, die wir mit unserer $ http-Anfrage verwenden. Dann richtet es ein Zusicherungsobjekt ein, erstellt eine $ http-Anfrage mit unserer abschließenden URL, und weil $ http eine Zusage zurückgibt, können wir nach unserer Anfrage .success oder .error aufrufen. Wir lösen dann unser Versprechen mit den iTunes Daten, oder wir lehnen es mit einer Nachricht ab, die sagt "Es gab einen Fehler".

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

Jetzt ist unsere Fabrik abgeschlossen. Wir sind nun in der Lage, 'myFactory' in einen beliebigen Controller zu injizieren, und dann können wir unsere Methoden aufrufen, die wir an unser Service-Objekt (setArtist, getArtist und callItunes) angehängt haben.

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

Im obigen Controller injizieren wir den Dienst 'myFactory'. Dann setzen wir Eigenschaften für unser $ scope-Objekt mit Daten von 'myFactory'. Der einzige knifflige Code oben ist, wenn Sie nie zuvor mit Versprechen gehandelt haben. Da callItunes eine Zusage zurückgibt, können wir die .then () -Methode verwenden und $ scope.data.artistData nur dann setzen, wenn unser Versprechen mit den iTunes-Daten erfüllt ist. Sie werden feststellen, dass unser Controller sehr "dünn" ist (Dies ist eine gute Programmierpraxis). Alle unsere logischen und persistenten Daten befinden sich in unserem Service, nicht in unserem Controller.

2) Service 
Das größte Problem beim Erstellen eines Service ist vielleicht, dass er mit dem neuen Keyword instanziiert wird. Für Sie JavaScript-Gurus sollte dies einen großen Hinweis auf die Art des Codes geben. Für diejenigen unter Ihnen, die einen eingeschränkten JavaScript-Hintergrund haben oder für diejenigen, die mit dem "neuen" Schlüsselwort nicht vertraut sind, lassen Sie uns ein paar Grundlagen zu JavaScript lesen, die uns helfen, die Natur eines Dienstes zu verstehen.

Um wirklich die Änderungen zu sehen, die beim Aufruf einer Funktion mit dem Schlüsselwort 'new' auftreten, erstellen wir eine Funktion und rufen sie mit dem Schlüsselwort 'new' auf. Dann zeigen wir, was der Interpreter tut, wenn er das Schlüsselwort 'new' sieht. Die Endergebnisse werden beide gleich sein.

Zuerst erstellen wir unseren Konstruktor.

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

Dies ist eine typische JavaScript-Konstruktorfunktion. Wenn wir nun die Funktion Person mit dem Schlüsselwort 'new' aufrufen, wird 'this' an das neu erstellte Objekt gebunden.

Nun fügen wir dem Prototyp unserer Person eine Methode hinzu, so dass sie für jede Instanz unserer "Klasse" verfügbar ist.

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

Da wir nun die Funktion sayName auf den Prototyp anwenden, kann jede Instanz von Person die Funktion sayName aufrufen, um den Namen dieser Instanz zu melden.

Jetzt, wo wir unsere Person-Konstruktorfunktion und unsere sayName-Funktion für ihren Prototyp haben, erstellen wir eigentlich eine Instanz von Person und rufen dann die sayName-Funktion auf.

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

Alles in allem sieht der Code zum Erstellen eines Person-Konstruktors, Hinzufügen einer Funktion zu seinem Prototyp, Erstellen einer Person-Instanz und anschließendem Aufruf der Funktion an seinem Prototyp folgendermaßen aus.

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’

Sehen wir uns jetzt an, was tatsächlich passiert, wenn Sie das Schlüsselwort "new" in JavaScript verwenden. Das erste, was Sie beachten sollten, ist, dass wir, nachdem wir in unserem Beispiel 'neu' verwendet haben, eine Methode (sayName) auf 'tyler' aufrufen können, als ob es ein Objekt wäre - das liegt daran, dass es so ist. Zuerst wissen wir, dass unser Person-Konstruktor ein Objekt zurückgibt, unabhängig davon, ob wir das im Code sehen oder nicht. Zweitens wissen wir, dass die Funktion sayName auf dem Prototyp und nicht direkt auf der Person-Instanz liegt. Das Objekt, das die Person-Funktion zurückgibt, muss bei fehlgeschlagenen Suchvorgängen an ihren Prototyp delegieren. Einfach ausgedrückt, wenn wir tyler.sayName () aufrufen, sagt der Interpreter: "OK, ich werde auf das 'tyler' Objekt schauen, das wir gerade erstellt haben, suchen Sie die sayName Funktion und rufen Sie sie dann auf. Moment mal, ich sehe es hier nicht - alles was ich sehe ist Name und Alter, lass mich den Prototyp überprüfen. Ja, es sieht so aus, als wäre es auf dem Prototyp, lass es mich so nennen. "

Im Folgenden finden Sie einen Code, wie Sie darüber nachdenken können, was das "neue" Keyword tatsächlich in JavaScript bewirkt. Es ist im Grunde ein Codebeispiel für den obigen Absatz. Ich habe die 'Interpreter-Ansicht' oder die Art, wie der Interpreter den Code in den Notizen sieht, gesetzt.

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

Wenn Sie nun wissen, was das "neue" Schlüsselwort in JavaScript wirklich bedeutet, sollte das Erstellen eines Dienstes in AngularJS einfacher zu verstehen sein.

Beim Erstellen eines Service ist es am wichtigsten zu wissen, dass Services mit dem Schlüsselwort "new" instanziiert werden. Wenn Sie dieses Wissen mit unseren obigen Beispielen kombinieren, sollten Sie nun erkennen, dass Sie Ihre Eigenschaften und Methoden direkt an "diese" anhängen, die dann vom Dienst selbst zurückgegeben werden. Werfen wir einen Blick darauf in Aktion.

Im Gegensatz zu dem, was wir ursprünglich mit dem Factory-Beispiel gemacht haben, müssen wir kein Objekt erstellen und dann dieses Objekt zurückgeben, da wir, wie schon oft erwähnt, das Schlüsselwort 'new' verwendet haben, damit der Interpreter dieses Objekt erstellen kann es ist ein Prototyp, dann gib es für uns zurück, ohne dass wir die Arbeit machen müssen.

Lassen Sie uns als Erstes unsere "private" und Hilfsfunktion erstellen. Dies sollte sehr vertraut sein, da wir genau das gleiche mit unserer Fabrik gemacht haben. Ich werde nicht erklären, was jede Zeile hier macht, weil ich das im Fabrikbeispiel getan habe. Wenn Sie verwirrt sind, lesen Sie das Fabrikbeispiel erneut.

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

Nun werden wir alle unsere Methoden, die in unserem Controller verfügbar sein werden, an "das" anhängen.

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

});

Jetzt, genau wie in unserer Fabrik, werden setArtist, getArtist und callItunes in jedem Controller verfügbar sein, an den myService übergeben wird. Hier ist der myService-Controller (der fast genau so wie unser Factory-Controller ist).

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

Wie bereits erwähnt, sind Dienste, sobald Sie wirklich verstehen, was "neu" ist, fast identisch mit Fabriken in AngularJS.

3) Anbieter

Die größte Sache, die Sie sich bei Providern merken sollten, ist, dass sie der einzige Service sind, den Sie in den app.config-Teil Ihrer Anwendung übertragen können. Dies ist von großer Bedeutung, wenn Sie einen Teil Ihres Dienstobjekts ändern müssen, bevor es überall in Ihrer Anwendung verfügbar ist. Obwohl es Services / Fabriken sehr ähnlich ist, gibt es einige Unterschiede, die wir diskutieren werden.

Zuerst haben wir unseren Provider in ähnlicher Weise aufgebaut, wie wir es mit unserem Service und unserer Fabrik getan haben. Die folgenden Variablen sind unsere "private" und Hilfsfunktion.

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

* Auch wenn irgendein Teil des obigen Codes verwirrend ist, schau dir den Factory-Bereich an, wo ich dir ausführlicher erläutere, was er alles macht.

Sie können sich Provider als drei Abschnitte vorstellen. Der erste Abschnitt sind die 'privaten' Variablen / Funktionen, die später (oben gezeigt) geändert / gesetzt werden. Der zweite Abschnitt enthält die Variablen / Funktionen, die in Ihrer app.config-Funktion verfügbar sind und daher geändert werden können, bevor sie irgendwo anders verfügbar sind (ebenfalls oben gezeigt). Es ist wichtig zu beachten, dass diese Variablen an das Schlüsselwort 'this' angehängt werden müssen. In unserem Beispiel ist nur 'thingFromConfig' verfügbar, das in der app.config geändert werden kann. Der dritte Abschnitt (siehe unten) enthält alle Variablen / Funktionen, die in Ihrem Controller verfügbar sind, wenn Sie den Dienst 'myProvider' an diesen spezifischen Controller übergeben.

Wenn Sie einen Dienst mit Provider erstellen, sind die einzigen Eigenschaften / Methoden, die in Ihrem Controller verfügbar sind, die Eigenschaften / Methoden, die von der Funktion $ get () zurückgegeben werden. Der folgende Code setzt $ get auf 'this' (von dem wir wissen, dass er irgendwann von dieser Funktion zurückgegeben wird). Diese $ get-Funktion gibt nun alle Methoden / Eigenschaften zurück, die im Controller verfügbar sein sollen. Hier ist ein Codebeispiel.

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

Jetzt sieht der vollständige Provider-Code so aus

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

Jetzt, genau wie in unserem Werk und Service, werden setArtist, getArtist und callItunes in jedem Controller verfügbar sein, an den wir myProvider übergeben. Hier ist der myProvider-Controller (der fast genauso wie unser Factory / Service-Controller ist).

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

Wie bereits erwähnt, besteht der Sinn des Erstellens eines Dienstes mit Provider darin, einige Variablen über die Funktion app.config ändern zu können, bevor das endgültige Objekt an den Rest der Anwendung übergeben wird. Lassen Sie uns ein Beispiel dafür sehen.

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

Jetzt können Sie sehen, wie 'dingFromConfig' als leere Zeichenfolge in unserem Provider ist, aber wenn dies im DOM angezeigt wird, wird 'Dieser Satz wurde gesetzt ...' angezeigt.


618
2017-12-24 13:15



Alle Dienstleistungen sind Singletons; Sie werden einmal pro App instanziiert. Sie können sein jeder Art, ob es sich um ein primitives Objekt, ein literales Objekt, eine Funktion oder sogar eine Instanz eines benutzerdefinierten Typs handelt.

Das value, factory, service, constant, und provider Methoden sind alle Anbieter. Sie lehren dem Injektor, wie die Dienste instanziiert werden.

Am ausführlichsten, aber auch am umfassendsten ist ein Provider   Rezept. Das noch vier Rezepttypen - Wert, Fabrik, Service und   Konstante - sind nur syntaktischer Zucker auf einem Provider-Rezept.

  • Das Wert Rezept ist der einfachste Fall, in dem Sie den Service selbst instanziieren und bereitstellen instanziierter Wert zum Injektor.
  • Das Werksrezept Gibt dem Injektor eine Factory-Funktion, die er aufruft, wenn er den Service instanziieren muss. Wenn es angerufen wird, das Fabrikfunktion erstellt und gibt die Dienstinstanz zurück. Die Abhängigkeiten des Service werden als Argumente der Funktionen eingefügt. Die Verwendung dieses Rezepts fügt folgende Fähigkeiten hinzu:
    • Möglichkeit, andere Dienste zu nutzen (Abhängigkeiten haben)
    • Service-Initialisierung
    • Verzögerte / verzögerte Initialisierung
  • Das Service-Rezept ist fast das gleiche wie das Factory-Rezept, aber hier ruft der Injector a auf Konstrukteur mit dem neuen Operator anstelle einer Factory-Funktion.
  • Das Anbieterrezept ist gewöhnlich Overkill. Es fügt eine weitere indirekte Ebene hinzu, indem Sie die Erstellung der Factory konfigurieren können.

Sie sollten das Providerrezept nur verwenden, wenn Sie eine API bereitstellen möchten   für die anwendungsweite Konfiguration, die vor dem   Anwendung startet. Dies ist normalerweise nur für wiederverwendbare Geräte interessant   Dienste, deren Verhalten möglicherweise geringfügig variieren muss   Anwendungen.


506
2018-02-01 12:58



AngularJS Factory, Service und Provider verstehen

Alle diese werden verwendet, um wiederverwendbare Singleton-Objekte zu teilen. Es hilft, wiederverwendbaren Code in Ihrer App / verschiedenen Komponenten / Modulen zu teilen.

Aus Dokumenten Service / Fabrik:

  • Faul instanziiert - Angular instanziiert nur einen Service / eine Factory, wenn eine Anwendungskomponente davon abhängt.
  • Singletons - Jede Komponente   Abhängig von einem Dienst erhält eine Referenz auf die einzelne Instanz   generiert von der Service Factory.

Fabrik

Eine Factory ist eine Funktion, mit der Sie vor dem Erstellen eines Objekts Logik bearbeiten / hinzufügen können. Anschließend wird das neu erstellte Objekt zurückgegeben.

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

Verwendung

Es kann nur eine Sammlung von Funktionen wie eine Klasse sein. Daher kann es in verschiedenen Controllern instanziiert werden, wenn Sie es in Ihre Controller / Factory / Direktive-Funktionen injizieren. Es wird nur einmal pro App instanziiert.

Bedienung

Einfach beim Betrachten der Dienste über den Array-Prototyp nachdenken. Ein Service ist eine Funktion, die ein neues Objekt mit dem Schlüsselwort 'new' instanziiert. Sie können Eigenschaften und Funktionen zu einem Serviceobjekt hinzufügen, indem Sie den Befehl verwenden thisStichwort. Im Gegensatz zu einer Factory gibt es nichts zurück (es gibt ein Objekt zurück, das Methoden / Eigenschaften enthält).

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

Verwendung

Verwenden Sie es, wenn Sie ein einzelnes Objekt in der gesamten Anwendung teilen müssen. Zum Beispiel authentifizierte Benutzerdetails, frei verwendbare Methoden / Daten, Dienstprogrammfunktionen usw.

Anbieter

Ein Provider wird verwendet, um ein konfigurierbares Serviceobjekt zu erstellen. Sie können die Serviceeinstellung über die Konfigurationsfunktion konfigurieren. Es gibt einen Wert zurück, indem Sie den Wert verwenden $get() Funktion. Das $get Funktion wird in der Laufphase in Winkel ausgeführt.

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

Verwendung

Wenn Sie für Ihr Serviceobjekt eine modulweise Konfiguration bereitstellen müssen, bevor Sie es bereitstellen, z. Angenommen, Sie möchten Ihre API-URL auf Basis Ihrer Umgebung festlegen dev, stage oder prod

HINWEIS 

Nur Provider wird in der Config-Phase von angular verfügbar sein, während   Service & Fabrik sind nicht.

Hoffe, das hat dein Verständnis darüber geklärt Fabrik, Service und Anbieter.


221
2017-11-14 06:25



Für mich kam die Offenbarung, als ich erkannte, dass sie alle auf die gleiche Weise arbeiten: indem sie etwas leiteten EinmalSpeichern Sie den Wert, den sie bekommen, und dann husten Sie auf der gleiche gespeicherte Wert wenn durch referenziert Abhängigkeitsspritze.

Sag, wir haben:

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

Der Unterschied zwischen den dreien ist der:

  1. aDer gespeicherte Wert kommt vom Ausführen fn.
  2. b'S gespeicherter Wert kommt von newIng fn.
  3. cDer gespeicherte Wert kommt vom ersten Aufruf einer Instanz newIng fnund dann läuft a $get Methode der Instanz.

Das bedeutet, dass es in AngularJS so etwas wie ein Cache-Objekt gibt, dessen Wert für jede Injektion nur einmal vergeben wird, wenn sie zum ersten Mal injiziert wurden und wo:

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

Deshalb benutzen wir this in Diensten und definieren a this.$get in Anbietern.


190
2017-07-22 11:39



Service vs Anbieter vs Fabrik:

Ich versuche es einfach zu halten. Es dreht sich alles um grundlegendes JavaScript-Konzept.

Lassen Sie uns zuerst darüber sprechen Dienstleistungen in AngularJS!

Was ist Service: In AngularJS, Bedienung ist nichts anderes als ein Singleton-JavaScript-Objekt, das einige nützliche Methoden oder Eigenschaften speichern kann. Dieses Singleton-Objekt wird auf Basis ngApp (Angular App) erstellt und unter allen Controllern innerhalb der aktuellen App geteilt. Wenn Angularjs ein Dienstobjekt instanziiert, registriert es dieses Dienstobjekt mit einem eindeutigen Dienstnamen. Jedes Mal, wenn wir eine Serviceinstanz benötigen, durchsucht Angular die Registrierung nach diesem Servicenamen und gibt den Verweis auf das Serviceobjekt zurück. So können wir Methoden, Zugriffseigenschaften usw. für das Serviceobjekt aufrufen. Sie haben vielleicht die Frage, ob Sie auch Eigenschaften, Methoden auf das Scope-Objekt von Controllern setzen können! Warum brauchen Sie Service-Objekt? Answers ist: Dienste werden von mehreren Controllern gemeinsam genutzt. Wenn Sie einige Eigenschaften / Methoden in das Bereichsobjekt eines Controllers einfügen, ist es nur für den aktuellen Bereich verfügbar. Wenn Sie jedoch Methoden, Eigenschaften für das Service-Objekt definieren, sind diese global verfügbar und können in jedem Bereich des Controllers durch die Eingabe dieses Service aufgerufen werden.

Wenn es also drei Controller-Bereiche gibt, seien Controller A, Controller B und Controller C, so teilen sich alle die gleiche Dienstinstanz.

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

Wie erstelle ich einen Service?

AngularJS bietet verschiedene Methoden an, um einen Dienst zu registrieren. Hier werden wir uns auf drei Methoden konzentrieren: Fabrik (..), Service (..), Provider (..);

Verwenden Sie diesen Link für die Codereferenz

Werksfunktion:

Wir können eine Fabrikfunktion wie unten definieren.

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

AngularJS bietet 'factory (' serviceName ', fnFactory)' Methode, die zwei Parameter, serviceName und eine JavaScript-Funktion verwendet. Angular erstellt die Dienstinstanz durch Aufrufen der Funktion fnFabrik () wie unten.

var serviceInstace = fnFactory();

Die übergebene Funktion kann ein Objekt definieren und dieses Objekt zurückgeben. AngularJS speichert diesen Objektverweis einfach auf eine Variable, die als erstes Argument übergeben wird. Alles, was von fnFactory zurückgegeben wird, wird an serviceInstance gebunden. Anstatt das Objekt zurückzugeben, können wir auch die Funktion, die Werte usw. zurückgeben. Was auch immer wir zurückgeben werden, steht der Serviceinstanz zur Verfügung.

Beispiel:

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

Service-Funktion:

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

Es ist der andere Weg, wir können einen Dienst registrieren. Der einzige Unterschied besteht darin, wie AngularJS versucht, das Serviceobjekt zu instanziieren. Dieses Mal verwendet angle ein neues Schlüsselwort und ruft die Konstruktorfunktion wie folgt auf.

var serviceInstance = new fnServiceConstructor();

In der Konstruktorfunktion können wir das Schlüsselwort 'this' verwenden, um dem Dienstobjekt Eigenschaften / Methoden hinzuzufügen. Beispiel:

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

Provider-Funktion:

Die Provider () -Funktion ist die andere Möglichkeit, Dienste zu erstellen. Lassen Sie uns daran interessiert sein, einen Dienst zu erstellen, der dem Benutzer lediglich eine Begrüßungsnachricht anzeigt. Wir möchten jedoch auch eine Funktionalität bereitstellen, so dass der Benutzer seine eigene Begrüßungsnachricht einstellen kann. In technischer Hinsicht möchten wir konfigurierbare Dienste erstellen. Wie können wir das tun? Es muss einen Weg geben, damit die App ihre eigenen Begrüßungsnachrichten weiterleiten kann und Angularjs sie der Factory / Konstruktor-Funktion zur Verfügung stellt, die unsere Services-Instanz erstellt. In diesem Fall kann die Funktion provider () ausgeführt werden. Mit der Funktion provider () können wir konfigurierbare Dienste erstellen.

Wir können konfigurierbare Dienste mithilfe der unten angegebenen Provider-Syntax erstellen.

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

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

Wie funktioniert die Provider-Syntax intern?

Das Objekt 1.Provider wird mit der Konstruktorfunktion erstellt, die wir in unserer Provider-Funktion definiert haben.

var serviceProvider = new serviceProviderConstructor();

2. Die Funktion, die wir in app.config () übergeben haben, wird ausgeführt. Dies wird Config-Phase genannt, und hier haben wir die Möglichkeit, unseren Service anzupassen.

configureService(serviceProvider);

Die Service-Instanz 3.Finally wird durch den Aufruf der Methode $ get von serviceProvider erstellt.

serviceInstance = serviceProvider.$get()

Beispielcode zum Erstellen von Diensten mithilfe der bereitgestellten Syntax:

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

Arbeitsdemo

Zusammenfassung:


Fabrik Verwenden Sie eine Factory-Funktion, die eine Serviceinstanz zurückgibt. serviceInstance = fnFactory ();

Bedienung Verwenden Sie eine Konstruktorfunktion und Angular rufen Sie diese Konstruktorfunktion auf, indem Sie das Schlüsselwort 'new' zum Erstellen der Dienstinstanz verwenden. serviceInstance = neu fnServiceConstructor ();

Anbieter Definiert eine providerConstructor-Funktion, diese providerConstructor-Funktion definiert eine Factory-Funktion $ erhalten . Angular ruft $ get () auf, um das Serviceobjekt zu erstellen. Die Provider-Syntax hat den zusätzlichen Vorteil, dass das Service-Objekt vor der Instanziierung konfiguriert wird. serviceInstance = $ get ();


133
2017-11-19 13:36



Wie von mehreren Leuten hier richtig ausgeführt wurde, sind Fabrik, Anbieter, Service und sogar Wert und Konstante Versionen derselben Sache. Sie können das allgemeinere sezieren provider in alle von ihnen. Wie so:

enter image description here

Hier ist der Artikel, aus dem dieses Bild stammt:

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


79
2017-08-02 05:37



Fabrik

Sie geben AngularJS eine Funktion, AngularJS wird den Rückgabewert zwischenspeichern und injizieren, wenn die Factory angefordert wird.

Beispiel:

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

Verwendung:

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

Bedienung

Sie geben AngularJS eine Funktion, die AngularJS aufrufen wird Neu um es zu instantiieren. Es ist die von AngularJS erstellte Instanz, die zwischengespeichert und injiziert wird, wenn der Dienst angefordert wird. Schon seit Neu wurde verwendet, um den Dienst, das Schlüsselwort, zu instanziieren Dies ist gültig und bezieht sich auf die Instanz.

Beispiel:

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

Verwendung:

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

Anbieter

Sie geben AngularJS eine Funktion und AngularJS ruft seine Funktion auf $get Funktion. Es ist der Rückgabewert von der $get Funktion, die zwischengespeichert und injiziert wird, wenn der Dienst angefordert wird.

Anbieter ermöglichen Ihnen, den Anbieter zu konfigurieren Vor AngularJS ruft den $get Methode, um das injizierbare zu bekommen.

Beispiel:

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

Verwendung (als Injektion in einen Controller)

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

Verwendung (vorher den Provider konfigurieren $get wird aufgerufen, um das injizierbare zu erstellen)

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

62
2018-05-19 19:53