Services vs. Factories in Angular

EDIT 2016. Beachten Sie, dass dieser Beitrag, der eine Wiederveröffentlichung eines Beitrags aus dem Jahr 2015 ist, sich auf Angular 1 bezieht. Ich beschäftige mich nicht mehr mit Frontends, daher kann ich nicht garantieren, dass dieser Beitrag für Angular 2 relevant ist ;).

Einer meiner Hack Reactor-Kollegen und ich haben kürzlich einen Rechner für die Behandlung von Bluthochdruck für Moxe Health gebaut, ein aufregendes Rock-Health-Unternehmen, das ein Datenbank-Integrationssystem und eine API aufbaut, die es jedem Entwickler ermöglicht, auf die elektronischen Krankenakten eines jeden Krankenhauses im Moxe-Netzwerk zuzugreifen. Ich freue mich darauf, in einem anderen Beitrag über Moxe und das Projekt zu sprechen. Wir haben das Frontend der App in Angular entwickelt, einem leistungsstarken Frontend-Framework mit Datenbindung und anderen fantastischen Funktionen. Eine Sache, die verwirrend war, war die Frage, wann man Services und wann Factories verwenden sollte. Stack Overflow hat einen guten Thread über den Unterschied zwischen den beiden, aber er lässt einige Analogien aus, von denen ich denke, dass sie für Entwickler nützlich sind, die ihre Javascript-Kenntnisse noch festigen.

In diesem Beitrag werden Sie den Unterschied zwischen den beiden lernen.

TLDR – Factories und Services haben so ziemlich die gleiche Funktionalität in Bezug auf ihre Fähigkeit, Methoden und Eigenschaften zu instanziieren und zu kapseln, ähnlich wie funktionale Instanziierung und pseudoklassische Instanziierungsmuster ähnliche Fähigkeiten haben. In der Angular-Community gibt es keine Präferenz für die Verwendung des einen oder des anderen. Factory- und Service-Rezepte sind nur syntaktischer Zucker auf dem Provider-Rezept. Die Frage, die Sie sich also stellen sollten, ist normalerweise nicht „Soll ich Fabriken oder Dienste verwenden?“, sondern „Soll ich funktionale Instanziierung oder pseudoklassische Instanziierung verwenden?“

Abgesehen von diesem Verständnis auf hoher Ebene besteht der wichtigste Unterschied darin, dass Fabriken aufgrund der unterschiedlichen Instanzierungsmuster Primitive und Funktionen zurückgeben können, Dienste jedoch nicht.

Primitive, Funktionen und Objekte, oh je!

Sehen Sie sich dieses JSFiddle an. Dank an Epokk, der den Großteil des Codes zur Verfügung gestellt hat. Ich habe ein paar Änderungen vorgenommen, die wiederum Entwicklern, die neu in Angular sind, helfen, die Unterschiede zu verstehen. Wenn Sie neu bei JSFiddle sind, ist es ein Werkzeug, das Ihnen erlaubt, leicht zu testen Interaktionen zwischen Ihren Javascript, HTML und CSS-Dateien. Sie können also mit dem Code herumspielen, ohne dass der ursprüngliche Code im Link überschrieben wird.

Sowohl der Dienst als auch die Fabrik in diesem Beispiel haben die gleiche Funktionalität, nämlich die Rückgabe der Zeichenkette „Hello World!“. Der Unterschied besteht darin, wie sie es tun.

Der Dienst instanziiert ein Objekt und weist die Funktion, die „Hello World!“ zurückgibt, der Eigenschaft „sayHello“ dieses Objekts zu:

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

Die Methode wird dann im Controller aufgerufen: helloWorldFromService.sayHello().

Die Fabrik liefert eine Funktion, die „Hello World!“ zurückgibt:

return function() { return "Hello, World!" };

Die Funktion wird dann im Controller aufgerufen: helloWorldFromFactory(). Beachten Sie, dass die Referenz der Fabrik auf die zurückgegebene Funktion verweist und nicht auf die Eigenschaft eines Objekts, dessen Wert eine Funktion ist, wie im Beispiel des Dienstes. Ein Dienst könnte dies niemals tun, da ein Dienst ein leeres Objekt instanziieren muss, dessen Referenz im Körper der Dienstfunktion ‚this‘ ist. Dienste geben immer Objekte zurück.

Hier ist der Teil der Fabriken, der verwirrend sein kann. Die Fabrik kann auch ein Objekt zurückgeben, das eine Methode ’sayHello‘ hat, ähnlich wie der Dienst:

return { sayHello: function() { return "Hello, World!" } };

Die Sie im Controller genau so aufrufen würden, wie Sie die sayHello-Funktion des Dienstes aufrufen würden: helloWorldFromFactory.sayHello().

Das letztere Fabrikformat ist nützlich, wenn man mehrere Methoden in einer Fabrik haben möchte:

return { sayHello: function() { return "Hello, World!" }, sayGoodbye: function() { return "Goodbye, World!" } };

Auch hier ist der Schlüssel, sich nicht in der Tatsache zu verfangen, dass man in Angular programmiert, und sich daran zu erinnern, dass die Unterschiede zwischen Diensten und Fabriken größtenteils die gleichen sind wie die Unterschiede zwischen pseudoklassischer Instanziierung und funktionaler Instanziierung.

Quellcode für Neugierige

Hier ist der Angular-Quellcode, der zeigt, dass Services & Factories auf das allgemeinere Provider-Feature aufgesetzt sind:

//provider function provider(name, provider_) { assertNotHasOwnProperty(name, 'service'); if (isFunction(provider_) || isArray(provider_)) { provider_ = providerInjector.instantiate(provider_); } if (!provider_.$get) { throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); } return providerCache = provider_; } //factory function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); } //service function service(name, constructor) { return factory(name, ); }

Beide, Service und Factory, erzeugen Singletons. Grundlegende funktionale vs. pseudoklassische Vererbungsmuster hier. Die Fabrik gibt zurück, was immer die factoryFn zurückgibt.

Der Dienst gibt eine Instanz einer Pseudoklasse zurück. Der Konstruktor der Pseudoklasse wird an den Service-Builder service() von Angular übergeben. Die Tatsache, dass der Konstruktor an den Service Builder Service übergeben wird (return $injector.instantiate(constructor)), kann verwirrend sein, aber stellen Sie es sich einfach als return new constructor() vor.

Happy coding!

Leave a Reply