Mylić o serwis vs Fabryka

Jak rozumiem, kiedy w fabryce zwracam obiekt, który zostaje wstrzyknięty do kontrolera. Kiedy wewnątrz usługi mam do czynienia z obiektem używając this i nie zwracając niczego.

Byłem przy założeniu, że usługa jest zawsze singletonem , i że nowy obiekt fabryczny jest wstrzykiwany do każdego kontrolera. Jak się jednak okazuje, obiekt fabryczny też jest singletonem?

Przykładowy kod do demonstracja:

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

factories.factory('User', function () {
  return {
    first: 'John',
    last: 'Doe'
  };
});

app.controller('ACtrl', function($scope, User) {
  $scope.user = User;
});

app.controller('BCtrl', function($scope, User) {
  $scope.user = User;
});

Przy zmianie user.first w ACtrl okazuje się, że user.first w BCtrl również się zmienia, np. User jest singletonem?

Moim założeniem było, że nowa instancja została wstrzyknięta do kontrolera z fabryką?

 623
Author: Zentaurus, 2012-12-07

20 answers

Wszystkie usługi kątowe to singletony :

Docs (see Services as singletons): https://docs.angularjs.org/guide/services

Wreszcie, ważne jest, aby zdać sobie sprawę, że wszystkie usługi Angular są singletonami aplikacji. Oznacza to, że na jeden wtryskiwacz przypada tylko jeden przypadek danej usługi.

Zasadniczo różnica między serwisem a fabryką jest następująca:

app.service('myService', function() {

  // service is just a constructor function
  // that will be called with 'new'

  this.sayHello = function(name) {
     return "Hi " + name + "!";
  };
});

app.factory('myFactory', function() {

  // factory returns an object
  // you can run some code before

  return {
    sayHello : function(name) {
      return "Hi " + name + "!";
    }
  }
});

Zobacz prezentację o $provide: http://slides.wesalvaro.com/20121113/#/

Te slajdy zostały użyte w jednym z Meetupów AngularJs: http://blog.angularjs.org/2012/11/more-angularjs-meetup-videos.html

 603
Author: matys84pl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-17 14:44:35

Dla mnie objawienie przyszło, gdy zdałem sobie sprawę, że wszystkie one działają w ten sam sposób: uruchamiając coś {16]} raz , zapisując otrzymaną wartość, a następnie kaszląc {16]} tę samą przechowywaną wartość gdy odwołuję się do iniekcji zależności.

Powiedzmy, że mamy:

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

Różnica między tymi trzema jest taka, że:

  1. Zapisana wartość a pochodzi z działania fn, innymi słowy: fn()
  2. b przechowywana wartość pochodzi z new ing fn, w innych słowa: new fn()
  3. Zapisana wartość c pochodzi z pierwszego pobrania instancji przez new ing fn, a następnie uruchomienia metody $get instancji

Co oznacza, że jest coś w rodzaju obiektu cache wewnątrz angular, którego wartość każdego wstrzyknięcia jest przypisywana tylko raz, kiedy zostały one wstrzyknięte po raz pierwszy, i gdzie: {]}

cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()
Dlatego używamy this w usługach i definiujemy this.$get w dostawcach. Mam nadzieję, że to pomoże.
 382
Author: Lucia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-19 13:23:48

Przykład na żywo

Przykład" hello world "

Z 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() {
    // In the provider function, you cannot inject any
    // service or factory. This can only be done at the
    // "$get" method.
 
    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()];
}​
 95
Author: EpokK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Istnieje również sposób na zwrócenie funkcji konstruktora, dzięki czemu można zwrócić newable klasy w fabrykach, jak to:

function MyObjectWithParam($rootScope, name) {
  this.$rootScope = $rootScope;
  this.name = name;
}
MyObjectWithParam.prototype.getText = function () {
  return this.name;
};

App.factory('MyObjectWithParam', function ($injector) {
  return function(name) { 
    return $injector.instantiate(MyObjectWithParam,{ name: name });
  };
}); 

Więc możesz to zrobić w kontrolerze, który używa MyObjectWithParam:

var obj = new MyObjectWithParam("hello"),

Zobacz tutaj pełny przykład:
http://plnkr.co/edit/GKnhIN?p=preview

A tutaj Strony grupy google, gdzie omawiano:
https://groups.google.com/forum/#! msg / 56sdorweoqg / b8hdPskxZXsJ

 57
Author: JustGoscha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-09 14:39:47

Oto podstawowe różnice:

Usługi

Składnia: module.service( 'serviceName', function );

Wynik: deklarując serviceName jako argument iniekcyjny, otrzymasz instancję funkcji przekazaną do module.service.

Użycie: może być użyteczne dla dzielenia funkcji użytkowych , które są użyteczne do wywołania przez zwykłe dołączenie () do iniekcyjnego odniesienia do funkcji. Może być również uruchamiany z injectedArg.call( this ) lub podobnym.

Fabryki

Składnia: module.factory( 'factoryName', function );

Wynik: deklarując factoryName jako argument iniekcyjny, otrzymasz wartość , która jest zwracana przez wywołanie referencji funkcji przekazanej do module.factory.

Użycie: może być przydatne do zwracania 'class' funkcji, która może być następnie nowa w celu utworzenia instancji.

Sprawdź również AngularJS documentation i podobne pytanie na stackoverflow na temat service vs factory.

Oto przykład użycia usługi i fabryka . Przeczytaj więcej o AngularJS service vs factory .

 51
Author: Manish Chhabra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:41

Dodaję do pierwszej odpowiedzi, tak myślę .service() jest przeznaczony dla osób, które napisały swój kod w bardziej obiektowym stylu (C# / Java) (używając tego słowa kluczowego i tworząc instancję obiektu poprzez funkcję prototype/Constructor).

Factory jest dla programistów, którzy piszą kod, który jest bardziej naturalny dla javascript / functional style kodowania.

Spójrz na kod źródłowy .serwis i .metoda fabryczna wewnątrz kątowa.js-wewnętrznie wszystkie wywołują metodę dostawcy:

  function provider(name, provider_) {
    if (isFunction(provider_)) {
      provider_ = providerInjector.instantiate(provider_);
    }
    if (!provider_.$get) {
      throw Error('Provider ' + name + ' must define $get factory method.');
    }
    return providerCache[name + providerSuffix] = provider_;
  }

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

  function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
  }
 27
Author: Anand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-12 07:25:06

Bardzo prosto:

.funkcja service-registered zostanie wywołana jako konstruktor (aka 'newed')

.funkcja zarejestrowana fabrycznie zostanie wywołana jako prosta funkcja

Oba zostaną wywołane po wywołaniu obiektu singleton, który zostanie wstrzyknięty do innych komponentów aplikacji.

 25
Author: bingles,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-25 14:17:41

Wszyscy dostawcy działają w ten sam sposób. Różne metody service, factory, provider po prostu pozwól osiągnąć to samo w mniejszym kodzie.

P. S. są też value i constant.

Każdy przypadek specjalny w łańcuchu zaczynający się od provider i kończący się na value ma dodatkowe ograniczenie. Więc aby zdecydować między nimi trzeba zadać sobie pytanie, które pozwoli Ci osiągnąć to, co chcesz z mniej kodu.

Oto zdjęcie, które pokazuje, co ja średnia:

Tutaj wpisz opis obrazka

Można podział i przewodnik odniesienia na blogu dostałem to zdjęcie z:

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

 20
Author: Luis Perez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-14 14:07:39

Oto kilka przykładów usług vs fabryk, które mogą być przydatne, aby zobaczyć różnicę między nimi. Zasadniczo usługa ma " nowe ..."wezwany, jest już instancjonowany. Fabryka nie jest tworzona automatycznie.

Podstawowe Przykłady

Zwraca obiekt klasy, który ma jedną metodę

Oto usługa, która ma jedną metodę:

angular.service('Hello', function () {
  this.sayHello = function () { /* ... */ };
});

Oto fabryka, która zwraca obiekt za pomocą metody:

angular.factory('ClassFactory', function () {
  return {
    sayHello: function () { /* ... */ }
  };
});

Return a wartość

Fabryka, która zwraca listę liczb:

angular.factory('NumberListFactory', function () {
  return [1, 2, 3, 4, 5];
});

console.log(NumberListFactory);

Usługa, która zwraca listę liczb:

angular.service('NumberLister', function () {
  this.numbers = [1, 2, 3, 4, 5];
});

console.log(NumberLister.numbers);

Wyjście w obu przypadkach jest takie samo, lista liczb.

Zaawansowane Przykłady

Zmienne"klasowe" za pomocą fabryk

W tym przykładzie definiujemy Przeciwfakturę, która zwiększa lub zmniejsza licznik i możesz uzyskać bieżącą liczbę lub dowiedzieć się, ile obiektów Przeciwfakturowych zostało utworzonych:

angular.factory('CounterFactory', function () {
  var number_of_counter_factories = 0; // class variable

  return function () {
    var count = 0; // instance variable
    number_of_counter_factories += 1; // increment the class variable

    // this method accesses the class variable
    this.getNumberOfCounterFactories = function () {
      return number_of_counter_factories;
    };

    this.inc = function () {
      count += 1;
    };
    this.dec = function () {
      count -= 1;
    };
    this.getCount = function () {
      return count;
    };
  }

})

Używamy CounterFactory do Utwórz wiele liczników. Możemy uzyskać dostęp do zmiennej klasy, aby zobaczyć, ile liczników zostało utworzonych:

var people_counter;
var places_counter;

people_counter = new CounterFactory();
console.log('people', people_counter.getCount());
people_counter.inc();
console.log('people', people_counter.getCount());

console.log('counters', people_counter.getNumberOfCounterFactories());

places_counter = new CounterFactory();
console.log('places', places_counter.getCount());

console.log('counters', people_counter.getNumberOfCounterFactories());
console.log('counters', places_counter.getNumberOfCounterFactories());

Wyjście tego kodu to:

people 0
people 1
counters 1
places 0
counters 2
counters 2
 13
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-29 07:56:13

"Factory" i "Service" to różne sposoby wykonywania di (dependency injection) w angular.

Więc kiedy zdefiniujemy DI za pomocą "usługi", jak pokazano w kodzie poniżej. Tworzy to nową globalną instancję obiektu "Logger" i wstrzykuje ją do funkcji.

app.service("Logger", Logger); // Injects a global object

Kiedy definiujesz DI używając "fabryki", nie tworzy ono instancji. Po prostu przekazuje metodę, a później konsument wewnętrznie musi wykonać wywołania do fabryki dla instancji obiektu.

app.factory("Customerfactory", CreateCustomer);

Poniżej znajduje się prosty obraz, który wizualnie pokazuje, jak proces DI dla" usługi " różni się od "fabryki".

Tutaj wpisz opis obrazka

Factory powinno być używane, gdy chcemy tworzyć różne typy obiektów w zależności od scenariuszy. Na przykład w zależności od scenariusza chcemy stworzyć prosty obiekt "Customer", lub "Customer" z obiektem "Address" lub "Customer" z obiektem "Phone". Oto szczegółowe wyjaśnienie tego paragrafu

Usługa powinna być używana, gdy mamy użyteczność lub współdzielone funkcje, które mają być wtryskiwane , takie jak Utility , Logger, Error handler itp.

 13
Author: Shivprasad Koirala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-18 05:40:32

Service style: ( prawdopodobnie najprostsza ) zwraca rzeczywistą funkcję: użyteczną do współdzielenia funkcji użytkowych, które są użyteczne do wywołania przez zwykłe dodanie () do iniekcji funkcji.

Usługa w AngularJS jest pojedynczym obiektem JavaScript, który zawiera zestaw funkcji
var myModule = angular.module("myModule", []);

myModule.value  ("myValue"  , "12345");

function MyService(myValue) {
    this.doIt = function() {
        console.log("done: " + myValue;
    }
}

myModule.service("myService", MyService);
myModule.controller("MyController", function($scope, myService) {

    myService.doIt();

});

Factory style: ( bardziej zaangażowany, ale bardziej wyrafinowany ) Zwraca wartość zwracaną funkcji: tworzy instancję obiektu jak nowy obiekt() w Javie.

Factory jest funkcją, która tworzy wartości. Gdy serwis, kontroler itp. potrzebuje wartości wtryskiwanej z fabryki, fabryka tworzy wartość na żądanie. Po utworzeniu wartość jest ponownie używana dla wszystkich usług, kontrolerów itp. które wymagają wstrzyknięcia.

var myModule = angular.module("myModule", []);

myModule.value("numberValue", 999);

myModule.factory("myFactory", function(numberValue) {
    return "a value: " + numberValue;
})  
myModule.controller("MyController", function($scope, myFactory) {

    console.log(myFactory);

});

Provider style: ( full blown, configurable version) zwraca wyjście funkcji $get: Configurable.

Dostawcy w AngularJS to najbardziej elastyczna forma fabryka, którą możesz stworzyć. Rejestrujesz dostawcę za pomocą modułu, tak jak to robisz w przypadku usługi lub fabryki, z wyjątkiem tego, że zamiast tego korzystasz z funkcji provider ().

var myModule = angular.module("myModule", []);

myModule.provider("mySecondService", function() {
    var provider = {};
    var config   = { configParam : "default" };

    provider.doConfig = function(configParam) {
        config.configParam = configParam;
    }

    provider.$get = function() {
        var service = {};

        service.doService = function() {
            console.log("mySecondService: " + config.configParam);
        }

        return service;
    }

    return provider;
});

myModule.config( function( mySecondServiceProvider ) {
    mySecondServiceProvider.doConfig("new config param");
});

myModule.controller("MyController", function($scope, mySecondService) {

    $scope.whenButtonClicked = function() {
        mySecondService.doIt();
    }

});

Src jenkov

<!DOCTYPE html>
    <html ng-app="app">
    <head>
    	<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
    	<meta charset=utf-8 />
    	<title>JS Bin</title>
    </head>
    <body ng-controller="MyCtrl">
    	{{serviceOutput}}
    	<br/><br/>
    	{{factoryOutput}}
    	<br/><br/>
    	{{providerOutput}}
    
    	<script>
    
    		var app = angular.module( 'app', [] );
    
    		var MyFunc = function() {
    
    			this.name = "default name";
    
    			this.$get = function() {
    				this.name = "new name"
    				return "Hello from MyFunc.$get(). this.name = " + this.name;
    			};
    
    			return "Hello from MyFunc(). this.name = " + this.name;
    		};
    
    		// returns the actual function
    		app.service( 'myService', MyFunc );
    
    		// returns the function's return value
    		app.factory( 'myFactory', MyFunc );
    
    		// returns the output of the function's $get function
    		app.provider( 'myProv', MyFunc );
    
    		function MyCtrl( $scope, myService, myFactory, myProv ) {
    
    			$scope.serviceOutput = "myService = " + myService;
    			$scope.factoryOutput = "myFactory = " + myFactory;
    			$scope.providerOutput = "myProvider = " + myProv;
    
    		}
    
    	</script>
    
    </body>
    </html>

Jsbin

<!DOCTYPE html>
<html ng-app="myApp">
<head>
	<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
	<meta charset=utf-8 />
	<title>JS Bin</title>
</head>
<body>
<div ng-controller="MyCtrl">
    {{hellos}}
</div>
	<script>

	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>

</body>
</html>

Jsfiddle

 8
Author: Premraj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-18 01:13:14

Podstawowa różnica polega na tym, że provider pozwala na ustawienie wartości funkcji prymitywnych (Nie-obiektów), tablicy lub funkcji zwrotnej do deklarowanej fabrycznie zmiennej, a zatem zwracanie obiektu musi być jawnie zadeklarowane i zwrócone.

Z drugiej strony usługa może być używana tylko do ustawienia zmiennej zadeklarowanej przez usługę na obiekt, dzięki czemu możemy uniknąć jawnego tworzenia i zwracania obiektów, podczas gdy z drugiej strony pozwala na użycie this słowo kluczowe.

Lub w skrócie " providerjest bardziej ogólną formą, podczas gdy service jest ograniczony tylko do obiektów".

 2
Author: yoel halb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-21 01:09:55

Tak rozumiałem różnicę między nimi pod względem wzorców projektowych:

Service : zwraca typ, który zostanie dodany do utworzenia obiektu tego typu. Jeśli używana jest analogia Javy, Service zwraca definicję klasy Java .

Factory : zwraca konkretny obiekt, który można natychmiast użyć. W analogii Javy Fabryka zwraca obiekt Java .

Część, która często myli ludzi (w tym mnie) jest to, że podczas wstrzykiwania usługa lub fabryka w kodzie mogą być używane w ten sam sposób, co masz w kodzie w obu przypadkach jest konkretny obiekt, który można natychmiast wywołać. Co oznacza, że w przypadku usługi, angular wywołuje "nowy" w deklaracji usługi w imieniu użytkownika. Myślę, że to zawiła koncepcja.

 2
Author: Hisham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-22 22:59:00

To byłaby najlepsza i krótka odpowiedź na zrozumienie usługi Vs Fabryka Vs dostawca

Źródło: https://groups.google.com/forum/#! msg / 56sdorweoqg / HuZsOsMvKv4J

Oto co ben mówi z demo http://jsbin.com/ohamub/1/edit?html, output

" w kodzie znajdują się komentarze ilustrujące podstawowe różnice, ale tutaj nieco je poszerzę. Dla przypomnienia, dopiero zaczynam się nad tym zastanawiać, więc jeśli Powiem coś, co jest złe, proszę, daj mi znać.

Usługi

Składnia : Moduł.service ('serviceName', function);

Result: podczas deklarowania serviceName jako argumentu iniekcyjnego otrzymasz rzeczywiste odniesienie do funkcji przekazane do modułu.obsługa.

Usage: może być użyteczne do współdzielenia funkcji użytkowych, które są użyteczne do wywołania przez zwykłe dołączenie () do iniekcyjnego odniesienia do funkcji. Może być również Uruchom z injectedArg.call( this ) lub podobne.

fabryki

Składnia : Moduł.factory ('factoryName', function);

Result: podczas deklarowania factoryName jako argumentu iniekcyjnego otrzymasz wartość, która jest zwracana przez wywołanie referencji funkcji przekazanej do modułu.fabryka.

Usage: może być przydatne do zwracania funkcji 'class', która może być następnie nowa w celu utworzenia przypadki.

dostawcy

Składnia : Moduł.provider ('providerName', function);

Result: podczas deklarowania providerName jako argumentu iniekcyjnego otrzymasz wartość, która jest zwracana przez wywołanie metody $ get referencji funkcji przekazywanej do modułu.dostawca.

Usage: może być przydatne do zwracania funkcji 'class', która może być następnie nowa w celu utworzenia instancji, ale wymaga to pewnego rodzaju konfiguracja przed wstrzyknięciem. Być może przydatne dla klas, które są wielokrotnego użytku w różnych projektach? Nadal trochę zamglona." Ben

 1
Author: Syed Ekram Uddin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-01 21:33:04

przez jakiś czas miałem to zamieszanie i staram się jak Mogę, aby zapewnić proste wyjaśnienie tutaj. Mam nadzieję, że to pomoże!

angular .factory i angular .service oba są używane do inicjalizacji usługi i działają w ten sam sposób.

Jedyną różnicą jest to, w jaki sposób chcesz zainicjować swoją usługę.

Oba są Singletony


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


Fabryka

App.fabryka(<service name>, <function with a return value>)

Jeśli chciałbyś zainicjalizuj swoją usługę z funkcji, którą masz z wartością zwracaną , musisz użyć tej metody factory.

Np.

function myService() {
  //return what you want
  var service = {
    myfunc: function (param) { /* do stuff */ }
  }
  return service;
}

app.factory('myService', myService);

Podczas wstrzykiwania tej usługi (np. do kontrolera):

  • Angular będzie wywoła podaną funkcję (jako myService()), aby zwrócić obiekt
  • Singleton - wywołany tylko raz, przechowywany i przekazujący ten sam obiekt.


Serwis

App.service (<service name>, <constructor function>)

Jeśli chcesz zainicjować swoją usługę z funkcji konstruktora (używając słowa kluczowego this), musisz użyć tej metody service.

Np.

function myService() {
  this.myfunc: function (param) { /* do stuff */ }
}

app.service('myService', myService);

Podczas wstrzykiwania tej usługi (np. do kontrolera):

  • Angular will newing your given function (as new myService()) to return the object
  • Singleton - wywołany tylko raz, przechowywany i przekazujący ten sam obiekt.


UWAGA: Jeśli jeśli używasz factory z <constructor function> lub service z <function with a return value>, to nie zadziała.

Przykłady-Dema

 1
Author: Safeer Hussain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-26 16:52:03

To właśnie pomogło mi zrozumieć różnicę, dzięki wpisowi na blogu Pascala Prechta.

Usługa jest metodą w module, która przyjmuje nazwę i funkcję, która definiuje usługę. Można wstrzykiwać i używać tej konkretnej usługi w innych komponentach, takich jak kontrolery, dyrektywy i filtry. Factory jest metodą w module, a także przyjmuje nazwę i funkcję, która definiuje fabrykę. Możemy również wstrzykiwać i używać tego samego sposobu, w jaki zrobiliśmy z obsługa.

Obiekty utworzone z new używają wartości właściwości prototype swojego konstruktora jako swojego prototypu, więc znalazłem Kod kątowy, który wywołuje obiekt.create(), która moim zdaniem jest funkcją service constructor, gdy zostanie utworzona. Jednak funkcja fabryczna jest tak naprawdę tylko funkcją, która jest wywoływana, dlatego musimy zwrócić obiekt dosłowny dla fabryki.

Oto kod angular 1.5, który znalazłem dla factory:

var needsRecurse = false;
    var destination = copyType(source);

    if (destination === undefined) {
      destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
      needsRecurse = true;
    }

Kątowe fragment kodu źródłowego funkcji factory ():

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

Pobiera nazwę i przekazywaną funkcję factory i zwraca dostawcę o tej samej nazwie, który ma metodę $ get, która jest naszą funkcją factory. Za każdym razem, gdy zapytasz injectora o konkretną zależność, w zasadzie zapyta on odpowiedniego dostawcę o instancję tej usługi, wywołując metodę $get (). Dlatego podczas tworzenia dostawców wymagane jest $get ().

Oto kod angular 1.5 Dla obsługa.

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

Okazuje się, że kiedy wywołujemy service (), to w rzeczywistości wywołuje factory()! Jednak nie tylko przekazuje naszą funkcję konstruktora serwisowego do fabryki w taki sposób, w jaki jest. Przekazuje również funkcję, która prosi wtryskiwacza o utworzenie instancji obiektu przez dany konstruktor.

Innymi słowy, jeśli wstrzykniemy gdzieś MyService, to co dzieje się w kodzie to:

MyServiceProvider.$get(); // return the instance of the service

Aby ponownie ją przekształcić, usługa wywołuje fabrykę, która jest metodą $get() u odpowiedniego dostawcy. Ponadto $injector.instantiate() jest metodą, która ostatecznie wywołuje obiekt.create() z funkcją konstruktora. Dlatego używamy "tego" w usługach.

Dla ES5 nie ma znaczenia, którego używamy: service() lub factory(), zawsze jest to fabryka, która jest nazywana, która tworzy dostawcę dla naszej usługi.

Możesz zrobić dokładnie to samo z usługami. Usługa jest jednak funkcją konstruktora, która nie uniemożliwia nam zwracania literałów obiektów. Więc możemy weź nasz kod serwisowy i napisz go w taki sposób, aby w zasadzie robił dokładnie to samo, co nasza fabryka lub innymi słowy, możesz napisać usługę jako fabrykę, aby zwrócić obiekt. Dlaczego większość ludzi zaleca korzystanie z fabryk zamiast usług? To najlepsza odpowiedź jaką widziałem, która pochodzi z książki Pawła Kozłowskiego: Mastering Web Application Development with AngularJS.

Metoda factory jest najczęstszym sposobem wprowadzania obiektów do Zależność AngularJS układ wtryskowy. Jest bardzo elastyczny i może zawierają wyrafinowaną logikę tworzenia. Ponieważ fabryki są regularne funkcji, możemy również skorzystać z nowego zakresu leksykalnego, aby symulować zmienne "prywatne". Jest to bardzo przydatne, ponieważ możemy ukryć szczegóły realizacji danej usługi."

 1
Author: James Drinkard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-05 13:00:11
  • z factory tworzysz obiekt wewnątrz factory i zwracasz go.
  • dzięki usłudze masz tylko standardową funkcję, która używa słowa kluczowego this do zdefiniowania funkcja.
  • z dostawcą jest $get definiujesz i można go użyć , Aby uzyskać obiekt, który zwraca dane.
 1
Author: Oskar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-29 15:24:55

W AngularJS istnieją trzy sposoby obsługi logiki biznesowej: (zainspirowane kursem Yaakova AngularJS ), które są:

  1. serwis
  2. fabryka
  3. dostawca

Tutaj będziemy rozmawiać tylko o serwis vs Fabryka

Serwis :

składnia:

App.js

 var app = angular.module('ServiceExample',[]);
 var serviceExampleController =
              app.controller('ServiceExampleController', ServiceExampleController);
 var serviceExample = app.service('NameOfTheService', NameOfTheService);

 ServiceExampleController.$inject = ['NameOfTheService'] //very important as this 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;
     }     
}

Indeks.html

<div ng-controller = "ServiceExampleController as serviceExample">
   {{serviceExample.data}}
</div>

Główne cechy Serwis:

  1. leniwie utworzone instancje: Jeśli usługa nie zostanie wstrzyknięta, nigdy nie zostanie utworzona instancja. Aby go użyć, musisz wstrzyknąć go do modułu.

  2. Singleton: jeśli zostanie wstrzyknięty do wielu modułów, wszystkie będą miały dostęp tylko do jednej konkretnej instancji. Dlatego bardzo wygodne jest udostępnianie danych między różnymi kontrolerami.

Fabryka

Teraz porozmawiajmy o fabryce w AngularJS

Najpierw przyjrzyjmy się składni :

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

Teraz używając powyższych dwóch w kontrolerze:

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

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

Cechy fabryki:

  1. Tego typu usługi są zgodne z wzorcem projektowym fabryki . Fabryka może być uważana za centralne miejsce, które tworzy nowe obiekty lub metody.

  2. To nie tylko produkuje singleton, ale także konfigurowalne usługi.

  3. Na .service() metoda jest fabryką , która zawsze produkuje ten sam rodzaj usługi, jakim jest singleton. Nie ma łatwego sposobu skonfigurowania jego zachowania. Ta metoda .service() jest zwykle używana jako skrót do czegoś, co nie wymaga żadnej konfiguracji.

 1
Author: Pritam Banerjee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-27 19:23:04

Dla krótkich i prostych wyjaśnień Patrz https://stackoverflow.com/a/26924234/5811973 .

Szczegółowe wyjaśnienia znajdują się w https://stackoverflow.com/a/15666049/5811973 .

Również z dokumentacji angularJs: Tutaj wpisz opis obrazka

 1
Author: Ishpreet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-30 11:50:55

Możesz zrozumieć różnicę za pomocą tej analogii-rozważ różnicę między normalną funkcją, która zwróci jakąś wartość, a funkcją konstruktora, która otrzyma instancję za pomocą nowego keyword.So tworzenie fabryki jest podobne do tworzenia normalnej funkcji, która zwróci jakąś wartość (prymitywną lub obiektową), podczas gdy tworzenie usługi jest jak tworzenie konstruktora funkcji (klasy OO), której możemy utworzyć instancję używając nowego słowa kluczowego. Jedyne, co należy zauważyć, to to, że gdy use service method to create services it will automatically create instance of it using dependency injection mechanism supported by AngularJS

 0
Author: Sourabh Ranka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-02 19:31:41