Как-то давно переводил статью «Понимание типов сервисов в AngularJS (constant, value, factory, service, provider)». На практике, конечно, не всё пригождается, поэтому в рамках понижения порога вхождения в Ангуляр, объясню проще.
Никаких фабрик в Ангуляре нет. Есть только провайдеры. Записываются так:
После этого Ангуляр создаст сервис из метода $get:
и его провайдер для настройки остальных параметров:
Провайдер мы используем для настройки сервиса (на стадии конфигурации):
Сам сервис — после запуска приложения:
Предположим, что настройки нам не нужны:
То, что мы сейчас записали есть ни что иное как фабрика. То же самое можно записать так:
Разумеется, и в этом случае Ангуляр создаст
Вывод:
P.S.
P.P.S Шпаргалка
Provider
Factory
Service
Value
Constant
P.P.P.S
Как Ангуляр узнает, какие параметры передать в конструктор? Дело в том, что
Никаких фабрик в Ангуляре нет. Есть только провайдеры. Записываются так:
app.provider('$helloWorld', function() { return { world: 'World', $get: function($hello) { return $hello + this.world; } } });
После этого Ангуляр создаст сервис из метода $get:
$helloWorld = function($hello) { return $hello + this.world; }
и его провайдер для настройки остальных параметров:
$helloWorldProvider = { world: 'World' }
Провайдер мы используем для настройки сервиса (на стадии конфигурации):
app.config(function($helloWorldProvider) { $helloWorldProvider.world = 'Piter'; })
Сам сервис — после запуска приложения:
app.controller('MainCtrl', function($scope, $helloWorld) { $scope.title = $helloWorld; // $hello + 'Piter' });
Предположим, что настройки нам не нужны:
app.provider('$helloWorld', function() { return { $get: function($hello) { return $hello + 'World'; } } });
То, что мы сейчас записали есть ни что иное как фабрика. То же самое можно записать так:
app.factory('$helloWorld', function($hello) { return $hello + 'World'; });
Разумеется, и в этом случае Ангуляр создаст
$helloWorldProvider, только он будет без параметров — пустым.Вывод:
factory, service, value, constant — всего лишь синтаксический сахар для provider P.S.
$hello это просто какой-то наш сервис, взятый для примера:app.factory('$hello', function() { return 'Hello'; });
P.P.S Шпаргалка
Provider
app.provider('$helloWorld', function() { return { world: 'World', $get: function($hello) { return $hello + this.world; } } });
Factory
app.factory('$helloWorld', function($hello) { return $hello + 'World'; }); // или app.provider('$helloWorld', function() { return { $get: function($hello) { return $hello + 'World'; } } });
Service
app.service('$helloWorld', HelloWorldClass); // или app.provider('$helloWorld', function() { return { $get: function($hello) { return new HelloWorldClass($hello); } } });
Value
app.value('$helloWorld', {greating: 'Hello'}); // или app.provider('$helloWorld', function() { return { $get: function() { return {greating: 'Hello'}; } } });
Constant
app.constant('$helloWorld', {world: 'Piter'}); // или app.provider('$helloWorld', function() { return { world: 'Piter', $get: function() { return this; //без $get } } }); // В config вызывается без суффикса Provider app.config(function($helloWorld) { ... })
P.P.P.S
function HelloWorldClass($hello) { ... } app.service('$helloWorld', HelloWorldClass);
Как Ангуляр узнает, какие параметры передать в конструктор? Дело в том, что
HelloWorldClass (да и любая функция в $get) запускается через $injector.invoke(fn), а это такая штука, которая читает код функции, вытаскивает аргументы из скобочек и подтягивает одноименные сервисы ($hello в нашем случае). Всё просто!