Как-то давно переводил статью «Понимание типов сервисов в 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
в нашем случае). Всё просто!