when - AngularJS: Service vs. Anbieter vs. Fabrik




angularjs when is a service instantiated (20)

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


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


Fabrik

Sie geben AngularJS eine Funktion. AngularJS speichert den Rückgabewert und fügt ihn ein, wenn die Factory angefordert wird.

Beispiel:

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

Verwendungszweck:

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

Bedienung

Sie geben AngularJS eine Funktion. AngularJS wird new aufrufen , um es zu instanziieren. Es ist die Instanz, die AngularJS erstellt, die zwischengespeichert und eingefügt wird, wenn der Dienst angefordert wird. Da new zur Instantiierung des Dienstes verwendet wurde, ist das Schlüsselwort this 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;
     }
});

Verwendungszweck:

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

Anbieter

Sie geben AngularJS eine Funktion, und AngularJS ruft seine $getFunktion auf. Dies ist der Rückgabewert der $getFunktion, der zwischengespeichert und eingefügt wird, wenn der Dienst angefordert wird.

Mit Providern können Sie den Provider konfigurieren, bevor AngularJS die $getMethode zum Abrufen des injizierbaren Objekts aufruft.

Beispiel:

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

Verwendung (als injizierbar in eine Steuerung)

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

Verwendung (die Konfiguration des Providers zuvor $getwird aufgerufen, um das Injektionsmittel zu erstellen)

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

Von der AngularJS-Mailingliste habe ich einen erstaunlichen Thread erhalten , der Service vs. Factory vs. Provider und deren Verwendung erläutert. Antworten zusammenstellen:

Dienstleistungen

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

Fabriken

Syntax: module.factory( 'factoryName', function );
Ergebnis: Wenn Sie factoryName als ein injizierbares Argument deklarieren, erhalten Sie den Wert, der durch Aufrufen der Funktionsreferenz zurückgegeben wird, die an module.factory übergeben wird .

Anbieter

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

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

here den bereitgestellten Code.

Hier eine großartige Erklärung von Misko:

provide.value('a', 123);

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

In diesem Fall gibt der Injektor den Wert einfach so zurück, wie er ist. Was aber, wenn Sie den Wert berechnen möchten? Dann eine Fabrik benutzen

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

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

factory ist also eine Funktion, die für die Wertschöpfung verantwortlich ist. Beachten Sie, dass die Factory-Funktion nach anderen Abhängigkeiten fragen kann.

Aber was ist, wenn Sie mehr OO sein wollen und eine Klasse namens Greeter haben?

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

Dann müssten Sie schreiben, um zu instanziieren

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

Dann könnten wir in diesem Controller nach einem Begrüßer fragen

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

Das ist aber viel zu wortreich. Ein kürzerer Weg, dies zu schreiben, wäre provider.service('greeter', Greeter);

Was aber, wenn wir die Greeter Klasse vor der Injektion konfigurieren wollten? 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');
}

service , factory und value beziehen sich alle auf den Anbieter.

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

Informationen zu AngularJS Factory, Service und Provider

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

Von Docs Service/Factory :

  • Lazily instantiiert - Angular instanziiert einen Dienst / eine Fabrik nur, wenn eine Anwendungskomponente davon abhängig ist.
  • Singletons - Jede Komponente, die von einem Dienst abhängig ist, erhält eine Referenz auf die von der Servicefabrik generierte Einzelinstanz.

Fabrik

Eine Factory ist eine Funktion, bei der Sie die Logik vor dem Erstellen eines Objekts bearbeiten oder hinzufügen können. Das neu erstellte Objekt wird 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;
});

Verwendungszweck

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

Bedienung

Denken Sie beim Betrachten der Services einfach über den Array-Prototyp nach. Ein Service ist eine Funktion, die ein neues Objekt mit dem Schlüsselwort 'new' instanziiert. Sie können einem Serviceobjekt Eigenschaften und Funktionen hinzufügen, indem Sie das thisSchlüsselwort verwenden. 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:
    };
});

Verwendungszweck

Verwenden Sie es, wenn Sie ein einzelnes Objekt in der gesamten Anwendung freigeben müssen. Zum Beispiel authentifizierte Benutzerdetails, freigegebene Methoden / Daten, Utility-Funktionen usw.

Anbieter

Ein Provider wird verwendet, um ein konfigurierbares Serviceobjekt zu erstellen. Sie können die Diensteinstellung über die Konfigurationsfunktion konfigurieren. Mit der $get()Funktion wird ein Wert zurückgegeben . Die $getFunktion wird in der Laufphase in eckig 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.
        };
    };
});

Verwendungszweck

Wenn Sie für Ihr Service-Objekt eine modulweise Konfiguration vor der Bereitstellung bereitstellen müssen, z. Angenommen , Sie Ihre API - URL auf Grundlage Ihrer Umgebung einstellen wollen wie dev, stageoderprod

HINWEIS

Nur der Provider wird in der Konfigurationsphase von angle verfügbar sein, Service & Factory jedoch nicht.

Ich hoffe, dies hat Ihr Verständnis von Factory, Service und Provider geklärt .


TL; DR

1) Wenn Sie eine Factory verwenden , erstellen Sie ein Objekt, fügen Eigenschaften hinzu und geben dann dasselbe Objekt zurück. Wenn Sie diese Factory an Ihren Controller übergeben, sind diese Eigenschaften des Objekts jetzt in Ihrem Controller durch 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 Service verwenden , instanziiert AngularJS es hinter den Kulissen mit dem Schlüsselwort 'new'. Aus diesem Grund fügen Sie Eigenschaften zu "this" hinzu, und der Dienst gibt "this" zurück. Wenn Sie den Dienst an Ihren Controller übergeben, sind die Eigenschaften von 'this' jetzt über diesen Dienst 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 der einzige Dienst, den Sie an Ihre .config () - Funktion übergeben können. Verwenden Sie einen Anbieter, wenn Sie eine modulweite Konfiguration für Ihr Serviceobjekt bereitstellen möchten, bevor Sie es verfügbar machen.

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 Dienstes. Es gibt wirklich nicht viel mehr als das, was der TL gesagt hat: DR. Sie erstellen einfach ein Objekt, fügen Eigenschaften hinzu und geben dann dasselbe Objekt zurück. Wenn Sie die Factory an Ihren Controller übergeben, stehen diese Eigenschaften des Objekts nun in Ihrem Controller durch Ihre Factory zur Verfügung. Ein ausführlicheres Beispiel ist unten.

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

Welche Eigenschaften wir mit "Service" verbinden, steht uns jetzt zur Verfügung, wenn wir "myFactory" an unseren Controller übergeben.

Nun wollen wir unserer Callback-Funktion einige "private" Variablen hinzufügen. Auf diese kann nicht direkt vom Controller aus zugegriffen werden, aber schließlich werden einige Getter / Setter-Methoden für 'service' eingerichtet, 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 / Funktion nicht an 'Service' anhängen. Wir erstellen sie einfach, um sie später zu verwenden oder zu ändern.

  • baseUrl ist die Basis-URL, die das iTunes-API benötigt
  • _artist ist der Künstler, den wir suchen möchten
  • _finalUrl ist die endgültige und vollständig erstellte URL, zu der wir iTunes anrufen
  • makeUrl ist eine Funktion, die unsere iTunes-freundliche URL erstellt und zurückgibt.

Jetzt, da unsere Helper / private Variablen und Funktion vorhanden sind, fügen wir dem 'Service'-Objekt einige Eigenschaften hinzu. Was immer wir für "Service" verwenden, kann direkt in dem Controller verwendet werden, an den wir "myFactory" übergeben.

Wir werden setArtist- und getArtist-Methoden erstellen, die einfach den Interpreten zurückgeben oder festlegen. Wir werden auch eine Methode entwickeln, 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 mit AngularJS noch nicht viel Erfahrung mit Versprechungen gesammelt haben, empfehle ich Ihnen dringend, einen tiefen Tauchgang durchzuführen.

Nachfolgend setArtist akzeptiert einen Interpreten und erlaubt Ihnen, den Interpreten festzulegen . getArtist gibt den Künstler zurück. callItunes ruft zuerst makeUrl () auf, um die URL zu erstellen, die wir mit unserer $ http-Anfrage verwenden. Dann wird ein Versprechungsobjekt eingerichtet, es wird eine $ http-Anforderung mit unserer abschließenden URL erstellt. Da $ http ein Versprechen zurückgibt, können wir .success oder .error nach unserer Anfrage aufrufen. Wir lösen dann unser Versprechen mit den iTunes-Daten oder lehnen es mit der Meldung "Es ist ein Fehler aufgetreten" ab.

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 fertig. Wir können jetzt "myFactory" in jeden Controller einspeisen, und wir können dann 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);
      })
  }
});

In der Steuerung oben injizieren wir den Dienst 'myFactory'. Wir legen dann Eigenschaften für unser $ scope-Objekt mit Daten aus 'myFactory' fest. Der einzige knifflige Code oben ist, wenn Sie sich noch nie mit Versprechen befasst haben. Da callItunes ein Versprechen zurückgibt, können wir die .then () -Methode verwenden und $ scope.data.artistData erst setzen, wenn unser Versprechen mit den iTunes-Daten erfüllt wird. Sie werden feststellen, dass unser Controller sehr dünn ist (dies ist eine gute Kodierungspraxis). Alle unsere logischen und permanenten Daten befinden sich in unserem Service, nicht in unserer Steuerung.

2) Service
Wenn Sie mit der Erstellung eines Dienstes zu tun haben, ist es vielleicht das Wichtigste, dass er mit dem Schlüsselwort 'new' instanziiert wird. Für Sie JavaScript-Gurus sollte dies einen großen Hinweis auf die Art des Codes geben. Für diejenigen, die nur über ein begrenztes JavaScript-Know-how verfügen, oder für diejenigen, die mit dem "neuen" Keyword nicht wirklich vertraut sind, sollten wir uns einige JavaScript-Grundlagen ansehen, die uns letztendlich beim Verständnis der Eigenschaften eines Services helfen.

Um die Änderungen wirklich zu sehen, wenn Sie eine Funktion mit dem Schlüsselwort 'new' aufrufen, erstellen Sie eine Funktion, rufen Sie sie mit dem Schlüsselwort 'new' auf und zeigen Sie dann, was der Interpreter macht, wenn er das Schlüsselwort 'new' sieht. Die Endergebnisse sind beide gleich.

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.

Jetzt fügen wir dem Prototyp unserer Person eine Methode hinzu, sodass sie auf jeder Instanz unserer Person 'class' verfügbar ist.

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

Da wir nun die sayName-Funktion in den Prototyp einfügen, kann jede Instanz von Person die sayName-Funktion aufrufen, um den Namen dieser Instanz zu warnen.

Nachdem wir nun die Person-Konstruktorfunktion und die Funktion sayName im Prototyp haben, erstellen wir eine Instanz von Person und rufen dann die Funktion sayName auf.

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

Der Code zum Erstellen eines Person-Konstruktors, zum Hinzufügen einer Funktion zum Prototyp, zum Erstellen einer Personeninstanz und zum anschließenden Aufrufen der Funktion für den Prototyp sieht also 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’

Schauen 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 nach der Verwendung von 'new' in unserem Beispiel eine Methode (sayName) für 'tyler' aufrufen können, als ob es ein Objekt wäre - weil 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 das Objekt, das die Funktion Person zurückgibt, bei fehlgeschlagenen Suchvorgängen an seinen Prototyp delegieren muss, da sich unsere sayName-Funktion im Prototyp und nicht direkt in der Personeninstanz befindet. Einfacher ausgedrückt: Wenn wir tyler.sayName () aufrufen, sagt der Interpreter: „OK, ich werde mir das soeben erstellte 'Tyler'-Objekt ansehen, die sayName-Funktion suchen und es dann aufrufen. Warten Sie eine Minute, ich sehe es hier nicht - alles, was ich sehe, ist Name und Alter, lassen Sie mich den Prototyp überprüfen. Ja, es sieht aus wie auf dem Prototyp, ich nenne es mal. “

Nachfolgend finden Sie Code, wie Sie darüber nachdenken können, was das "neue" Schlüsselwort in JavaScript tatsächlich tut. Es ist im Grunde ein Codebeispiel des obigen Absatzes. Ich habe die "Interpreteransicht" oder die Art und Weise, wie der Interpreter den Code in Notizen sieht, eingefügt.

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 tut, sollte das Erstellen eines Service in AngularJS einfacher zu verstehen sein.

Wenn Sie einen Service erstellen, müssen Sie zunächst wissen, dass Services mit dem Schlüsselwort 'new' instanziiert werden. Wenn Sie dieses Wissen mit den oben genannten Beispielen kombinieren, sollten Sie nun erkennen, dass Sie Ihre Eigenschaften und Methoden direkt an "this" anhängen, das dann vom Service selbst zurückgegeben wird. Schauen wir uns das in Aktion an.

Im Gegensatz zu dem ursprünglichen Factory-Beispiel müssen wir kein Objekt erstellen und dieses Objekt zurückgeben, da wir, wie schon oft erwähnt, das Schlüsselwort 'new' verwendet haben, damit der Interpreter das Objekt erstellen kann, das er delegieren kann Es ist ein Prototyp, der uns dann zurückgegeben wird, ohne dass wir die Arbeit machen müssen.

Zuerst sollten wir unsere 'private' und Helper-Funktion erstellen. Dies sollte sehr bekannt aussehen, da wir mit unserer Fabrik genau dasselbe gemacht haben. Ich werde nicht erklären, was jede Zeile hier tut, 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;
  }
});

Jetzt fügen wir alle unsere Methoden, die in unserem Controller verfügbar sein werden, zu 'this'.

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 wie in unserer Fabrik stehen setArtist, getArtist und callItunes in jedem Controller zur Verfügung, an den wir myService übergeben. Hier ist der myService Controller (der fast genauso aussieht wie unser Factory Controller).

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 Services, wenn Sie wirklich verstanden haben, was "neu" ist, fast identisch mit den Fabriken in AngularJS.

3) Anbieter

Das Wichtigste an Providern ist, dass sie der einzige Dienst sind, den Sie an den Teil app.config Ihrer Anwendung übergeben können. Dies ist äußerst wichtig, wenn Sie einen Teil Ihres Serviceobjekts ändern müssen, bevor es an anderer Stelle in Ihrer Anwendung verfügbar ist. Obwohl Services / Factories sehr ähnlich sind, gibt es einige Unterschiede, die wir besprechen werden.

Zuerst haben wir unseren Provider auf eine ähnliche Weise eingerichtet, 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;
  }
}

* Wenn ein Teil des obigen Codes verwirrend ist, schaue mal in der Factory-Sektion nach, wo ich erkläre, was das alles ausführlicher macht.

Sie können sich Provider als drei Bereiche vorstellen. Der erste Abschnitt enthält die 'privaten' Variablen / Funktionen, die später geändert / eingestellt werden (siehe oben). 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 an anderer Stelle verfügbar sind (auch oben gezeigt). Es ist wichtig zu wissen, dass diese Variablen an das Schlüsselwort 'this' angehängt werden müssen. In unserem Beispiel steht nur "thingFromConfig" zur Änderung in der app.config zur Verfügung. Der dritte Abschnitt (siehe unten) enthält alle Variablen / Funktionen, die in Ihrer Steuerung verfügbar sind, wenn Sie den Dienst 'myProvider' an diese bestimmte Steuerung übergeben.

Beim Erstellen eines Dienstes mit Provider stehen in Ihrem Controller nur die Eigenschaften / Methoden zur Verfügung, die von der $ get () - Funktion zurückgegeben werden. Der folgende Code setzt $ get auf 'this' (von dem wir wissen, dass er von dieser Funktion zurückgegeben wird). Die $ 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
    }
  }

Nun 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 unserer Factory und in Service, werden setArtist, getArtist und callItunes in jedem Controller verfügbar sein, in den wir myProvider übergeben. Hier ist der myProvider-Controller (der fast genauso ist wie unser Werks- / Service-Controller).

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 springende Punkt beim Erstellen 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 "thingFromConfig" in unserem Provider als leere Zeichenfolge angezeigt wird. Wenn dies jedoch im DOM angezeigt wird, lautet die Meldung "Dieser Satz wurde festgelegt ...".


Werk: Das Werk, in dem Sie ein Objekt erstellen, und es zurückschicken.
Dienst: Der Dienst, den Sie gerade haben, verfügt über eine Standardfunktion, die das Schlüsselwort this verwendet, um die Funktion zu definieren.
provider: Es gibt einen $ get-Provider, den Sie definieren, und es kann verwendet werden, um das Objekt zu erhalten, das die Daten zurückgibt.


Diese Antwort bezieht sich auf das Thema / die Frage

wie Factory, Service und Constant - Ist ein Anbieterrezept nur syntaktischer Zucker?

ODER

wie fabrik, service und anbieter intern ähnlich sind

im Grunde ist was passiert

Wenn Sie ein factory()it-Set erstellen, functiondas Sie im zweiten Argument des Providers angegeben haben, $getund es zurückgeben ( provider(name, {$get:factoryFn })), erhalten Sie lediglich providereine Eigenschaft / Methode außer$get der provider(das bedeutet, dass Sie dies nicht konfigurieren können).

Quellcode der Fabrik

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

Wenn Sie einen service()it-Befehl zurückgeben, geben Sie ein factory () mit einem ein function, das die injiziert constructor(gibt die Instanz des Konstruktors zurück, die Sie in Ihrem Service bereitgestellt haben) und gibt es zurück

Quellcode des Dienstes

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

Im Grunde erhalten Sie in beiden Fällen schließlich einen Provider, der $ set auf Ihre von Ihnen bereitgestellte Funktion festgelegt ist. Sie können jedoch etwas mehr als $ get angeben, da Sie ursprünglich in provider () für config-Block angeben können


Es gibt bereits gute Antworten, aber ich möchte diese hier nur teilen.

Zunächst einmal: Provider ist der Weg / das Rezept, um ein service(Singleton-Objekt) zu erstellen , von dem angenommen wird, dass es von $ injector injiziert wird (wie AngulaJS mit dem IoC-Muster umgeht).

Und Value, Factory, Service und Constant (4 Wege) - der syntaktische Zucker über Provider Weg / Empfang.

Es wurde ein Service vs FactoryTeil abgedeckt: https://www.youtube.com/watch?v=BLzNCkPn3ao

Beim Service geht es neweigentlich um ein Keyword, bei dem wir wissen, dass es 4 Dinge tut:

  1. erstellt ein neues Objekt
  2. verknüpft es mit seinem prototypeObjekt
  3. verbindet sich contextmitthis
  4. und kehrt zurück this

Und Fabrik ist über die Factory - Pattern - enthält Funktionen , die Objekte wie dieser Dienst zurückzukehren.

  1. Fähigkeit zur Nutzung anderer Dienste (Abhängigkeiten haben)
  2. Service-Initialisierung
  3. verzögerte / faule Initialisierung

Und dieses einfache / kurze Video: deckt auch Provider ab : https://www.youtube.com/watch?v=HvTZbQ_hUZY (dort sehen Sie, wie sie von der Fabrik zum Anbieter gehen)

Das Providerrezept wird hauptsächlich in der App-Konfiguration verwendet, bevor die App vollständig gestartet / initialisiert wurde.


Ich habe etwas Interessantes beim Herumspielen mit Anbietern bemerkt.

Die Sichtbarkeit von Injektionsmitteln unterscheidet sich für die Anbieter von Dienstleistungen und Fabriken. Wenn Sie eine AngularJS als "konstant" deklarieren (z. B. myApp.constant('a', 'Robert');), können Sie sie in Dienste, Fabriken und Anbieter einfügen.

Wenn Sie jedoch einen AngularJS-Wert angeben (z. B.., myApp.value('b', {name: 'Jones'});), Können Sie ihn in Dienste und Fabriken einfügen, jedoch NICHT in die Provider-Erstellung. Sie können es jedoch in die $getFunktion einfügen, die Sie für Ihren Provider definieren. Dies wird in der AngularJS-Dokumentation erwähnt, ist aber leicht zu übersehen. Sie finden es auf der Seite% bieten in den Abschnitten zu den Wert- und Konstantenmethoden.

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>

Mein Verständnis ist unten sehr einfach.

Factory: Sie erstellen einfach ein Objekt in der Factory und senden es zurück.

Bedienung:

Sie haben nur eine Standardfunktion, die dieses Schlüsselwort verwendet, um eine Funktion zu definieren.

Anbieter:

Es gibt ein von $getIhnen definiertes Objekt, mit dem das Objekt abgerufen werden kann, das Daten zurückgibt.


Nachdem ich all diese Beiträge gelesen hatte, erzeugte es mehr Verwirrung für mich. Aber trotzdem ist alles wertvolle Information. Schließlich fand ich folgende Tabelle, die Informationen mit einfachem Vergleich gibt

  • Der Injektor erstellt mithilfe von Rezepten zwei Arten von Objekten: Dienste und Objekte für spezielle Zwecke
  • Es gibt fünf Rezepttypen, die definieren, wie Objekte erstellt werden: Wert, Fabrik, Dienst, Anbieter und Konstante.
  • Fabrik und Service sind die am häufigsten verwendeten Rezepte. Der einzige Unterschied besteht darin, dass das Service-Rezept für Objekte eines benutzerdefinierten Typs besser funktioniert, während die Factory JavaScript-Grundelemente und -Funktionen erzeugen kann.
  • Das Rezept des Providers ist der Kernrezepttyp, und alle anderen sind nur syntaktischer Zucker.
  • Anbieter ist der komplexeste Rezepttyp. Sie brauchen es nicht, es sei denn, Sie erstellen einen wiederverwendbaren Code, der global konfiguriert werden muss.
  • Alle Sonderobjekte mit Ausnahme des Controllers werden über Werksrezepte definiert.

Und für Anfänger verstehen Sie: - Dies kann den Anwendungsfall nicht korrigieren, aber auf hohem Niveau ist dies das, was für diese drei Fälle gilt.

  1. Wenn Sie im Winkelmodul verwenden möchten, sollte die Konfigurationsfunktion als Provider angelegt werden

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

  1. Ajax Call oder Integrationen von Drittanbietern müssen Service sein .
  2. Für Datenmanipulationen erstellen Sie es als Factory

Für grundlegende Szenarien verhält sich factory & Service gleich.


Nur zur Verdeutlichung der AngularJS-Quelle können Sie sehen, dass ein Dienst nur die Factory-Funktion aufruft, die wiederum die Provider-Funktion aufruft:

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

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

All die guten Antworten schon. Ich möchte noch einige Punkte zu Service und Fabrik hinzufügen . Zusammen mit dem Unterschied zwischen Service / Werk. Und man kann auch Fragen haben wie:

  1. Sollte ich service oder fabrik verwenden? Was ist der Unterschied?
  2. Tun sie dasselbe oder haben sie dasselbe Verhalten?

Beginnen wir mit dem Unterschied zwischen Service und Werk:

  1. Beide sind Singletons : Wenn Angular diese zum ersten Mal als Abhängigkeit findet, wird eine einzige Instanz von Service / Factory erstellt. Sobald die Instanz erstellt wurde, wird dieselbe Instanz für immer verwendet.

  2. Kann zum Modellieren eines Objekts mit Verhalten verwendet werden : Sie können sowohl über Methoden als auch über interne Zustandsvariablen verfügen. Die Art, wie Sie diesen Code schreiben, unterscheidet sich jedoch.

Dienstleistungen:

Ein Service ist eine Konstruktorfunktion, die Angular durch Aufruf von new instanziiert yourServiceName(). Das bedeutet ein paar Dinge.

  1. Funktionen und Instanzvariablen sind Eigenschaften von this.
  2. Sie müssen keinen Wert zurückgeben. Wenn Angular aufruft new yourServiceName(), erhält es das thisObjekt mit allen Eigenschaften, die Sie darauf ablegen.

Beispielbeispiel:

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

Wenn Angular diesen MyServiceDienst in einen von ihm abhängigen Controller einspritzt , erhält dieser Controller eine MyServiceFunktion, mit der er Funktionen aufrufen kann, z. B. MyService.aServiceMethod ().

Seien Sie vorsichtig mitthis :

Da der erstellte Service ein Objekt ist, können die darin enthaltenen Methoden beim Aufruf darauf verweisen:

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

Sie könnten versucht sein, ScoreKeeper.setScoreeine Versprechungskette aufzurufen , zum Beispiel, wenn Sie die Partitur initialisiert haben, indem Sie sie vom Server abholen: $http.get('/score').then(ScoreKeeper.setScore).Das Problem dabei ist, dass ScoreKeeper.setScoremit thisgebunden an gerufen wird nullund Sie Fehler erhalten. Der bessere Weg wäre $http.get('/score').then(ScoreKeeper.setScore.bind(ScoreKeeper)). Ob Sie dies in Ihren Servicemethoden verwenden oder nicht, seien Sie vorsichtig, wie Sie sie nennen.

Rückgabe eines Wertes aus einemService :

Aufgrund der Funktionsweise von JavaScript-Konstruktoren erhält der Aufrufer , wenn Sie einen komplexen Wert (ie, an Object)aus einer constructorFunktion zurückgeben, dieses Objekt anstelle der Instanz dieser Instanz.

Das bedeutet , dass Sie im Grunde das Werk Beispiel von unten copy-paste, ersetzen factorymit service, und es wird funktionieren:

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

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

Wenn Angular also Ihren Dienst mit dem neuen MyService () erstellt, wird dieses API-Objekt anstelle der MyService-Instanz abgerufen.

Dies ist das Verhalten für komplexe Werte (Objekte, Funktionen), nicht jedoch für primitive Typen.

Fabriken:

Eine Factory ist eine einfache alte Funktion, die einen Wert zurückgibt. Der Rückgabewert ist das, was in vom Werk abhängige Dinge injiziert wird. Ein typisches Factory-Muster in Angular besteht darin, ein Objekt mit Funktionen als Eigenschaften wie folgt zurückzugeben:

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

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

  return api;
});

Der injizierte Wert für eine Factory-Abhängigkeit ist der Rückgabewert der Factory und muss kein Objekt sein. Es könnte eine Funktion sein

Antworten zu den obigen Fragen 1 und 2:

Zum größten Teil bleiben Sie einfach bei der Verwendung von Fabriken für alles. Ihr Verhalten ist leichter zu verstehen. Es gibt keine Möglichkeit zu entscheiden, ob ein Wert zurückgegeben werden soll oder nicht, und außerdem sollten keine Fehler eingeführt werden, wenn Sie das Falsche tun.

Ich bezeichne sie immer noch als "Dienste", wenn ich davon rede, sie als Abhängigkeiten zu injizieren.

Service / Factory-Verhalten ist sehr ähnlich, und einige Leute werden sagen, dass beide in Ordnung sind. Das stimmt schon, aber ich finde es einfacher, den Ratschlägen von John Papas Styleguide zu folgen und einfach bei den Fabriken zu bleiben. **


Als Referenz dieser Seite und der docs.angularjs.org/guide/providers (die sich seit dem letzten Mal, als ich das letzte Mal angeschaut habe, anscheinend sehr verbessert zu haben scheint), habe ich die folgende reale (-ish) Weltdemo zusammengestellt, die 4 der 5 verschiedenen Anbietervarianten verwendet. Value, Constant, Factory und ausgewachsener Anbieter.

HTML:

<div ng-controller="mainCtrl as main">
    <h1>{{main.title}}*</h1>
    <h2>{{main.strapline}}</h2>
    <p>Earn {{main.earn}} per click</p>
    <p>You've earned {{main.earned}} by clicking!</p>
    <button ng-click="main.handleClick()">Click me to earn</button>
    <small>* Not actual money</small>
</div>

App

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

// A CONSTANT is not going to change
app.constant('range', 100);

// A VALUE could change, but probably / typically doesn't
app.value('title', 'Earn money by clicking');
app.value('strapline', 'Adventures in ng Providers');

// A simple FACTORY allows us to compute a value @ runtime.
// Furthermore, it can have other dependencies injected into it such
// as our range constant.
app.factory('random', function randomFactory(range) {
    // Get a random number within the range defined in our CONSTANT
    return Math.random() * range;
});

// A PROVIDER, must return a custom type which implements the functionality 
// provided by our service (see what I did there?).
// Here we define the constructor for the custom type the PROVIDER below will 
// instantiate and return.
var Money = function(locale) {

    // Depending on locale string set during config phase, we'll
    // use different symbols and positioning for any values we 
    // need to display as currency
    this.settings = {
        uk: {
            front: true,
            currency: '£',
            thousand: ',',
            decimal: '.'
        },
        eu: {
            front: false,
            currency: '€',
            thousand: '.',
            decimal: ','
        }
    };

    this.locale = locale;
};

// Return a monetary value with currency symbol and placement, and decimal 
// and thousand delimiters according to the locale set in the config phase.
Money.prototype.convertValue = function(value) {

    var settings = this.settings[this.locale],
        decimalIndex, converted;

    converted = this.addThousandSeparator(value.toFixed(2), settings.thousand);

    decimalIndex = converted.length - 3;

    converted = converted.substr(0, decimalIndex) +
        settings.decimal +
        converted.substr(decimalIndex + 1);    

    converted = settings.front ?
            settings.currency + converted : 
            converted + settings.currency; 

    return converted;   
};

// Add supplied thousand separator to supplied value
Money.prototype.addThousandSeparator = function(value, symbol) {
   return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, symbol);
};

// PROVIDER is the core recipe type - VALUE, CONSTANT, SERVICE & FACTORY
// are all effectively syntactic sugar built on top of the PROVIDER construct
// One of the advantages of the PROVIDER is that we can configure it before the
// application starts (see config below).
app.provider('money', function MoneyProvider() {

    var locale;

    // Function called by the config to set up the provider
    this.setLocale = function(value) {
        locale = value;   
    };

    // All providers need to implement a $get method which returns
    // an instance of the custom class which constitutes the service
    this.$get = function moneyFactory() {
        return new Money(locale);
    };
});

// We can configure a PROVIDER on application initialisation.
app.config(['moneyProvider', function(moneyProvider) {
    moneyProvider.setLocale('uk');
    //moneyProvider.setLocale('eu'); 
}]);

// The ubiquitous controller
app.controller('mainCtrl', function($scope, title, strapline, random, money) {

    // Plain old VALUE(s)
    this.title = title;
    this.strapline = strapline;

    this.count = 0;

    // Compute values using our money provider    
    this.earn = money.convertValue(random); // random is computed @ runtime
    this.earned = money.convertValue(0);

    this.handleClick = function() { 
        this.count ++;
        this.earned = money.convertValue(random * this.count);
    };
});

Arbeits demo .


Eine weitere Klarstellung ist, dass Fabriken Funktionen / Primitive erstellen können, während Services dies nicht können. Schauen Sie sich dieses jsFiddle basierend auf Epokk an: http://jsfiddle.net/skeller88/PxdSP/1351/ .

Die Factory gibt eine Funktion zurück, die aufgerufen werden kann:

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

Die Factory kann auch ein Objekt mit einer Methode zurückgeben, die aufgerufen werden kann:

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

Der Dienst gibt ein Objekt mit einer Methode zurück, die aufgerufen werden kann:

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

Weitere Informationen finden Sie in einem Beitrag, den ich zum Unterschied geschrieben habe: http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/


Etwas spät zur Party. Ich denke jedoch, dass dies für diejenigen hilfreich ist, die sich mit der Entwicklung von Angular JS Custom Services unter Verwendung von Factory-, Service- und Providermethoden vertraut machen möchten (oder Klarheit darüber haben).

Ich bin auf dieses Video gestoßen, in dem die Methoden von Factory, Service und Providern für die Entwicklung von AngularJS Custom Services klar beschrieben werden:

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

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

Der hier veröffentlichte Code wird direkt aus der obigen Quelle kopiert, um den Lesern zu helfen.

Der Code für den werkseitigen benutzerdefinierten Dienst lautet wie folgt (was sowohl für die Synchronisierungs- als auch für die Async-Version gilt, wenn der HTTP-Dienst aufgerufen wird):

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

Der Code für die "Service" -Methodik für benutzerdefinierte Services (dies ist ziemlich ähnlich zu "factory", unterscheidet sich jedoch vom Standpunkt der Syntax):

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

}]);

Der Code für die "Provider" -Methodik für benutzerdefinierte Services (dies ist erforderlich, wenn Sie einen Service entwickeln möchten, der konfiguriert werden kann):

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

Schließlich die Benutzeroberfläche, die mit einem der oben genannten Dienste arbeitet:

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


Hier ist ein Broilerplate-Code, den ich als Code-Vorlage für die Objektfabrik in AngularjS entwickelt habe. Ich habe eine Car / CarFactory als Beispiel zur Veranschaulichung verwendet. Ermöglicht einfachen Implementierungscode in der Steuerung.

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

Hier ist ein einfacheres Beispiel. Ich verwende einige Bibliotheken von Drittanbietern, die ein "Position" -Objekt erwarten, das Längen- und Breitengrad freigibt, jedoch über andere Objekteigenschaften. Ich wollte den Herstellercode nicht hacken, also habe ich die Objekte "Position" angepasst, an denen ich vorbeikam.

    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

;


Ich kenne eine Menge hervorragender Antworten, aber ich muss meine Erfahrungen mit der Verwendung von
1. servicefür die meisten Standardfälle
2. factoryzur Erstellung des Dienstes für diese bestimmte Instanz mitteilen

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

und mit:

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

Lassen Sie uns die drei Arten des Umgangs mit der Geschäftslogik in AngularJS auf einfache Weise diskutieren: ( Inspiriert von Yaakovs Kurs Coursera AngularJS )

SERVICE :

Syntax:

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>

Merkmale des Dienstes:

  1. Lazily Instantiated : Wenn es nicht injiziert wird, wird es niemals instanziiert. Um es zu verwenden, muss es in ein Modul eingespritzt werden.
  2. Singleton : Wenn sie in mehrere Module injiziert werden, haben alle nur Zugriff auf eine bestimmte Instanz. Daher ist es sehr praktisch, Daten zwischen verschiedenen Controllern gemeinsam zu nutzen.

FABRIK

Zuerst werfen wir einen Blick auf die Syntax:

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

Verwenden Sie nun die beiden obigen in der Steuerung:

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

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

Merkmale der fabrik:

  1. Folgt dem Fabrik-Designmuster. Die Fabrik ist ein zentraler Ort, an dem neue Objekte oder Funktionen hergestellt werden.
  2. Produziert nicht nur Singleton-Dienste, sondern auch anpassbare Dienste.
  3. Bei der .service()Methode handelt es sich um eine Factory , die immer die gleiche Art von Service erzeugt, nämlich einen Singleton, und ohne eine einfache Möglichkeit, ihr Verhalten zu konfigurieren. Diese .service()Methode wird normalerweise als Abkürzung für etwas verwendet, für das keinerlei Konfiguration erforderlich ist.

ANBIETER

Sehen wir uns zuerst die Syntax an:

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

}

Merkmale des Providers:

  1. Provider ist die flexibelste Methode zum Erstellen von Diensten in Angular.
  2. Wir können nicht nur eine dynamisch konfigurierbare Factory erstellen, sondern bei der Verwendung der Factory mit der Provider-Methode die Factory nur einmal beim Bootstrapping unserer gesamten Anwendung konfigurieren.
  3. Die Factory kann dann in der gesamten Anwendung mit benutzerdefinierten Einstellungen verwendet werden. Mit anderen Worten, wir können diese Factory vor dem Start der Anwendung konfigurieren. In der Winkeldokumentation wird tatsächlich erwähnt, dass die Providermethode tatsächlich hinter den Kulissen ausgeführt wird, wenn wir unsere Services mit einer .serviceoder einer .factoryMethode konfigurieren .
  4. Das $getist eine Funktion, die direkt mit der Provider-Instanz verbunden ist. Diese Funktion ist eine Werksfunktion . Mit anderen Worten, es ist genau wie das, das wir verwenden, um die .factoryMethode bereitzustellen . In dieser Funktion erstellen wir unseren eigenen Service. Diese $getEigenschaft, das ist eine Funktion, macht den Provider zum Provider . AngularJS erwartet, dass der Provider eine $ get -Eigenschaft besitzt, deren Wert eine Funktion ist, die Angular als Factory-Funktion behandelt. Das Besondere an diesem Provider-Setup ist jedoch die Tatsache, dass wir configObjekte innerhalb des Service-Providers bereitstellen können , und dies führt normalerweise zu Voreinstellungen, die wir später in dem Schritt überschreiben können, in dem wir die gesamte Anwendung konfigurieren können.

Wie von mehreren Personen hier richtig angegeben, sind Fabrik, Anbieter, Service und sogar Wert und Konstante Versionen derselben Sache. Sie können die allgemeineren providerin alle teilen. So wie:

Hier ist der Artikel, von dem dieses Bild stammt:





angularjs-provider