Каковы различия между Service
, Provider
и Factory
в AngularJS?
Из списка рассылки AngularJS я получил удивительную тему, которая объясняет, что такое сервис vs фабрика vs провайдер и их использование при инъекциях. Компилирую ответы:
Синтаксис: module.service( 'serviceName', function )
Результат: При объявлении serviceName в качестве инжектируемого аргумента вам будет предоставлен экземпляр функции. Другими словами new FunctionYouPassedToService()
.
Синтаксис: module.factory( 'factoryName', function )
Результат: При объявлении factoryName как инжектируемого аргумента вам будет предоставлено значение, которое возвращается при вызове функции, переданной в module.factory.
Синтаксис: module.provider( 'providerName', function )
Результат: При объявлении providerName в качестве инжектируемого аргумента вам будет предоставлен (new ProviderFunction()).$get()
. Функция-конструктор инстанцируется до вызова метода $get - ProviderFunction
- это ссылка на функцию, переданная в module.provider.
Преимущество провайдеров в том, что их можно настроить на этапе конфигурации модуля.
Приведенный код см. на здесь.
Вот отличное дальнейшее объяснение от Misko:
provide.value('a', 123);
function Controller(a) {
expect(a).toEqual(123);
}
В этом случае инжектор просто возвращает значение как есть. Но что если вы хотите вычислить значение? Тогда используйте фабрику
provide.factory('b', function(a) {
return a*2;
});
function Controller(b) {
expect(b).toEqual(246);
}
Итак, factory
- это функция, которая отвечает за создание значения. Обратите внимание, что функция фабрики может запрашивать другие зависимости.
Но что если вы хотите быть более ОО и иметь класс под названием Greeter?
function Greeter(a) {
this.greet = function() {
return 'Hello ' + a;
}
}
Тогда для инстанцирования вам придется написать
provide.factory('greeter', function(a) {
return new Greeter(a);
});
Затем мы можем запросить 'greeter' в контроллере следующим образом
function Controller(greeter) {
expect(greeter instanceof Greeter).toBe(true);
expect(greeter.greet()).toEqual('Hello 123');
}
Но это слишком многословно. Более короткий способ написать это - provider.service('greeter', Greeter);
.
Но что, если мы хотим настроить класс Greeter
перед инъекцией? Тогда мы могли бы написать
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);
};
});
Тогда мы можем сделать следующее:
angular.module('abc', []).config(function(greeter2Provider) {
greeter2Provider.setSalutation('Halo');
});
function Controller(greeter2) {
expect(greeter2.greet()).toEqual('Halo 123');
}
В качестве примечания, service
, factory
и value
являются производными от provider.
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;
});
};
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>
ТЛ;ДР <БР><БР> 1) Когда вы используете фабрики создать объект, добавить свойства к нему, а затем вернуться в тот же самый объект. Когда вы пройдете этот завод в свой контроллер, те свойства объекта теперь будет доступен на этом контроллере через ваш завод.
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) Когда вы используете услуги, в AngularJS создает его за кулисами с ‘новой’ ключевое слово. Из-за этого вы добавите свойств "этого" и служба будет возвращать "это". Когда вы проходите службу в контроллере, эти свойства на " это " теперь будет доступен на этом контроллере через ваш сервис.
app.controller(‘myServiceCtrl’, function($scope, myService){
$scope.artist = myService.getArtist();
});
app.service(‘myService’, function(){
var _artist = ‘Nelly’;
this.getArtist = function(){
return _artist;
}
});
<БР><БР> 3) поставщики единственный сервис, вы можете пройти на ваш .конфигурации (функции). Использовать провайдера, Если вы хотите обеспечить модуль конфигурации объекта обслуживания, прежде чем сделать его доступным.
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’;
});
<БР><БР> Не простил 1) завод <БР> Заводы являются наиболее популярным способом создать и настроить службу. Там действительно не намного больше, чем ТЛ;сказал доктор. Вы просто создать объект, добавить свойства к нему, а затем вернуться в тот же объект. Затем, когда вы проходите фабрики в ваш контроллер, те свойства объекта теперь будет доступен на этом контроллере через ваш завод. Более подробную примере ниже.
app.factory(‘myFactory’, function(){
var service = {};
return service;
});
Теперь все свойства, которое мы придаем "услуга" будет доступна нам, когда мы проходим ‘myFactory в наш контроллер. Теперь давайте добавим некоторые "частные" переменных нашей функции обратного вызова. Они не будут доступны прямо из контроллера, но мы в конечном итоге создали некоторые методы геттер/сеттер на "услуги", чтобы иметь возможность изменять эти "частные" переменных, когда это необходимо.
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;
});
Здесь вы заметите, мы не соединил эти переменные/функции "обслуживание". Мы просто создаем их для того, чтобы применить или изменить их позже.
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;
});
Теперь наша фабрика полно. Теперь мы можем вставить myFactory в любой контроллер и тогда мы сможем называть наши методы, которые мы прикрепили к нашему объекту обслуживания (setArtist, getArtist и callItunes).
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);
})
}
});
В контроллере выше мы вводим в эксплуатацию ‘myFactory’. Затем мы устанавливаем свойства, на наш объект $scope с данными myFactory’. Только выше хитрый код, если вы никогда не сталкивались с обещаниями перед. Потому что callItunes возвращает обещание, мы можем использовать .тогда() метод, и установить только $объем.данных.artistData раз наше обещание выполнено с данными в iTunes. Вы заметите, что наш регулятор очень ‘тонкий’ (это хорошая практика кодирования). Вся наша логика и постоянных данных находится в нашем сервисе, а не в наш контроллер. <БР><БР> 2) обслуживание <БР> Возможно, самая большая вещь, чтобы знать, когда имеем дело с созданием сервиса заключается в том, что он создается с помощью ключевого слова new. Для вас гуру в JavaScript это должно дать вам большой намек на природу этого кодекса. Для тех из вас, с ограниченным фон в JavaScript или для тех, кто не слишком хорошо знакомы с тем, что ‘новый’ ключевое слово на самом деле, давайте рассмотрим некоторые JavaScript основы, что в конечном итоге поможет нам в понимании природы услуги. Чтобы действительно увидеть изменения, которые происходят, когда вы вызываете функцию с помощью ключевого слова new, давайте создадим функцию и вызвать ее с помощью ключевого слова new, а потом покажем, что переводчик делает, когда он видит "нового" сайта. Конечные результаты будут те же. Сначала давайте создадим наш конструктор.
var Person = function(name, age){
this.name = name;
this.age = age;
}
Это типичная функция-конструктор в JavaScript. Теперь всякий раз, когда мы вызываем функцию человека с помощью ключевого слова new, ‘то’ будет связано на вновь созданный объект. Теперь давайте добавим метод на прототип нашего человека, он будет доступен на каждом экземпляре класса наш человек‘’.
Person.prototype.sayName = function(){
alert(‘My name is ‘ + this.name);
}
Теперь, поскольку мы ставим функцию sayName на прототип, каждый человек сможет вызвать функцию sayName в предупреждение того, что имя экземпляра. Теперь, мы имеем нашу функцию-конструктор, человек, и наша функция sayName на свой прототип, давайте на самом деле создать экземпляр человека, затем вызвать функцию sayName.
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’
Так что все вместе код для создания конструктор человек, добавив функцию на образец, создавая экземпляр человека, и затем вызов функции по ее прототип выглядит так.
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’
Теперь давайте посмотрим на то, что на самом деле происходит, когда вы используете "новые" ключевое слово в JavaScript. Первое, что вы должны заметить, что после использования "нового" в нашем примере, мы можем вызвать метод (sayName) на ‘Тайлер’ как если бы это был объект - это потому, что это. Итак, во-первых, мы знаем, что наш человек конструктор возвращает объект, будь то можно увидеть, что в коде или нет. Во-вторых, мы знаем, что наша функция sayName находится на прототип, а не непосредственно на экземпляр человека, объект, функции человека возвращается должны быть делегируя своему прототипу по искусству поиска. В более простых терминах, когда мы называем Тайлер.sayName() переводчик говорит “ок, я буду смотреть на объект ‘Тайлер’ мы только что создали, найдите sayName функции, затем вызвать его. Погодите, я ее здесь не вижу - я вижу только имя и возраст, позвольте мне проверить прототип. Ага, похоже на прототип, позвольте мне назвать его”.. Ниже приведен код, как вы можете думать о том, что ‘новые’ ключевое слово на самом деле делать в JavaScript. Это в основном пример кода выше. Я поставил ‘переводчик смотреть’ или как переводчик видит код внутри заметки.
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;
}
Теперь, обладая этим знанием, что ‘новый’ ключевое слово на самом деле не в JavaScript, создание сервиса на AngularJS, должно быть легче понять. Самое главное, чтобы понять, при создании Службы, зная, что сервисы создаются с помощью ключевого слова new. Сочетая эти знания с наших примерах выше, теперь вы должны признать, что вы будете прикреплять свои свойства и методы, непосредственно ‘этот’, который затем будет возвращен из самого сервиса. Давайте посмотрим на это в действии. В отличие от того, что мы первоначально сделали с завода, например, нам не нужно создавать объект, а затем вернуть этот объект, потому что, как уже отмечалось неоднократно ранее, мы использовали ‘новые’ ключевое слово, чтобы переводчик будет создавать этот объект, его делегировать это прототип, а затем вернуть его для нас без нас того, чтобы сделать работу. Перво-наперво, давайте создадим наш "частный" и вспомогательную функцию. Это должно выглядеть очень знакомо, так как мы сделали то же самое с нашей фабрикой. Я не буду объяснять что означает каждая строка здесь, потому что я сделал это в пример завод, если вы запутались, перечитайте пример фабрики.
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;
}
});
Сейчас мы придаем все наши методы, которые будут доступны в нашем контроллере для ‘этого’.
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;
}
});
Теперь так же, как на нашем заводе, setArtist, getArtist, и callItunes будут доступны в зависимости от того, какой контроллер проходим MyService с на. Вот контроллер MyService С (который почти точно так же, как наш контроллер фабрики).
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);
})
}
});
Как я уже упоминал ранее, когда вы действительно понимаете, что каждый новый, сервисы почти идентичны заводы на AngularJS. <БР><БР> 3) провайдер Самое главное, чтобы помнить о поставщиках заключается в том, что они единственные услуги, которые вы можете пройти в приложение.конфигурации часть вашего приложения. Это имеет огромное значение, если вам нужно изменить какую-то часть своего объекта обслуживания, прежде чем он доступен везде в вашем приложении. Хотя очень похоже на услуги/фабрик, есть несколько различий, которые мы будем обсуждать. Сначала мы создали наш поставщик аналогичным образом мы поступили с нашим сервисом и фабрики. Переменные ниже приведены наши "частные" и вспомогательную функцию.
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;
}
}
*Опять же, если какая-либо часть этого кода сбивает с толку, проверьте раздел заводе, где я объясню, что все это более подробно. Можно подумать поставщиков, имеющих трех разделов. Первый раздел-это "частный" переменные/функции, которые будут изменены/установить позднее (см. выше). Второй раздел-это переменные/функции, которые будут доступны в вашем приложении.функция config и поэтому доступны для изменения, прежде чем они доступны в другом месте (Также см. выше). Важно отметить, что эти переменные должны быть прикреплены к ‘это’ ключевое слово. В нашем примере, только ‘thingFromConfig’ быть доступен для изменения в приложение.конфиг. В третьем разделе (см. ниже) все переменные/функции, которые будут доступны в вашем контроллере, когда вы передаете в службу myProvider в том, что конкретный контроллер. При создании сервиса с провайдером, только свойства/методы, которые будут доступны в вашем контроллере эти свойства/методы, которые возвращаются из $вам (функции). Приведенный ниже код добавляет $вам на " это " (что мы знаем, что в конечном итоге будут возвращены из функции). Теперь, что $get возвращает функция все методы/свойства, которые мы хотим быть доступен в контроллере. Вот пример кода.
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
}
}
Теперь полный код провайдера выглядит так
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
}
}
});
Теперь так же, как на нашем заводе и услуг, setArtist, getArtist, и callItunes будут доступны в зависимости от того, какой контроллер проходим в myProvider. Вот контроллер myProvider (что почти точно так же, как наша фабрика контроллера/услуги).
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;
});
Как уже упоминалось раньше, весь смысл создания сервиса с поставщика, чтобы иметь возможность изменять некоторые переменные через приложение.функция config до конечного объекта передается к остальной части приложения. Давайте посмотрим пример.
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';
});
Теперь вы можете увидеть, как ‘thingFromConfig’ является пустая строка в нашего провайдера, но когда это появляется в доме, это будет ‘этот приговор был установлен...’.
Все услуги одиночек; они получают инстанцирован один раз для каждого приложения. Они могут быть любых, будь то примитивный, литерал объекта, функции или даже экземпляр пользовательского типа.
В значение
, фабрика
, служба
, постоянный
, и поставщик
методы у всех провайдеров. Они учат инжектора, как создавать сервисы.
и GT; самый подробный, но и наиболее всеобъемлющим является поставщиком
рецепт. В оставшиеся четыре рецепт типы — значения, фабрики, обслуживание и постоянн — - это просто синтаксический сахар поверх рецепт провайдер.
вы должны использовать рецепт провайдер, только если вы хотите предоставлять API для применения конфигурации, которые должны быть сделаны до запуска приложения. Обычно это интересно только многоразовые услуги, поведение которых может потребоваться незначительно отличаться от применения.
декоратор
.Понимание в AngularJS Фабрика, Услуги и поставщика
Все они используются, чтобы обмениваться предметами многоразового синглтон. Это помогает делиться многоразовый код вашего приложения/различных компонентов/модулей.
из документов сервис/Фабрика:
- лениво инстанцировать – углового только создает сервис/фабрика, когда компонент приложения зависит от него.
- одиночек – каждый компонент В зависимости от сервиса получает ссылку на один экземпляр генерируемые службы завода.
Завод-это функция, где можно манипулировать/добавить логику, прежде чем создавать объект, то созданный объект будет возвращен.
app.factory('MyFactory', function() {
var serviceObj = {};
//creating an object with methods/functions or variables
serviceObj.myFunction = function() {
//TO DO:
};
//return that object
return serviceObj;
});
Использование
Это может быть просто коллекция функций как класса. Следовательно, он может быть создан в разных контроллерах, когда ты вводишь его в свой контроллер/завод/директивы функции. Он создается только один раз для каждого приложения.
Сервис ####
Просто глядя на услуги, думаете о прототипе массива. Служба-это функция, которая создает новый объект с помощью 'новый' сайта. Вы можете добавлять свойства и функции к объекту обслуживания с помощью "этого" сайта. В отличие от завода, оно не'т вернуть все, (он возвращает объект, который содержит методы/свойства).
app.service('MyService', function() {
//directly binding events to this context
this.myServiceFunction = function() {
//TO DO:
};
});
Использование
Используйте его, когда вам нужно использовать один объект в приложении. Например, прошедшие проверку детали, пользователь, доля-возможности методов/данных, функций полезности и т. д.
Поставщик используется для создания настраиваемого объекта обслуживания. Вы можете настроить параметра из функции конфигурации. Она возвращает значение с помощью $получить()
функция. В $получить
функция выполняется на этапе запуска в угловой.
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.
};
};
});
Использование
Когда вам нужно предоставить модуль-мудрый конфигурации объекта обслуживания, прежде чем сделать его доступным, например. предположим, вы хотите установить свой URL-адрес API на основе вашей среде, как гигант
, этап
или прод
Примечание
будут доступны в config фазы угловых, в то время как единственным поставщиком обслуживание &ампер; заводе не.
Надеюсь, что это прояснилось ваше понимание о фабрике, Услуги и поставщика.
Для меня было откровение, когда я поняла, что все они работают таким же образом: путем выполнения чего-то однажды, хранение ценности, которые они получают, а потом кашель до Что же сохраненное значение при обращении через инъекции зависимостей]1.
Сказать, что мы имеем:
app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);
Разница между тремя заключается в том, что:
а
'ы сохраненное значение приходит от работы ФН
.б
сохраненное значение происходит от новых подработок
ФН`.С
с сохраненным значением происходит от получения экземпляра новых подработок ФН
, а затем запустить `$вам метод экземпляра.Это значит, что есть что-то вроде объекта кэш внутри в AngularJS, чья стоимость каждой инъекции присваивается только один раз, когда они'вэ были впрыснуты в первый раз, и где:
cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()
Вот почему мы используем этот сервис, и определить это.$выйти на поставщиков.
Услуги против поставщика против завода:
Я пытаюсь сохранить его простым. Это's Все о Основные понятия в JavaScript.
Прежде всего, позвольте'поговорим о услуги на AngularJS!
Что такое сервис: На AngularJS, сервис это ничто иное, как статический объект JavaScript, которые могут хранить некоторые полезные методы или свойства. Это одноэлементный объект создается в ngApp(угловой приложение) и она является общей для всех контроллеров в рамках текущего приложения. Когда в AngularJS инстанцировать объект обслуживания, это зарегистрировать этот объект с уникальным именем сервиса. Поэтому каждый раз, когда нам нужен экземпляр службы, угловые поиск в реестре по этому имени службы, и он возвращает ссылку на объект обслуживания. Такие, что мы можем вызвать метод, свойства, доступ и т. д. На объект обслуживания. Вы можете иметь вопрос, что вы также можете поместить свойств, методов охвата объекта контроллеров! Так зачем нужен объект обслуживания? Ответы: услуги распределяются между несколькими области контроллера. Если вы поставить некоторые свойства/методы в контроллере's объекта объем , она будет доступна только в текущей области. Но при определении методов, свойств объекта обслуживания, она будет доступна во всем мире и могут быть доступны в любой контроллер'С рамки, вводя эту услугу.
Так что если есть три области контроллера, пусть будет controllerA, controllerB и controllerC, все будут разделять один и тот же экземпляр сервиса.
<div ng-controller='controllerA'>
<!-- controllerA scope -->
</div>
<div ng-controller='controllerB'>
<!-- controllerB scope -->
</div>
<div ng-controller='controllerC'>
<!-- controllerC scope -->
</div>
Как создать службу?
AngularJS обеспечивают различные методы, чтобы зарегистрировать службу. Здесь мы сосредоточимся на трех фабричные методы(..),службы(..),провайдера(..);
[Используйте эту ссылку для справки код][1]
Мы можем определить функцию фабрики как ниже.
factory('serviceName',function fnFactory(){ return serviceInstance;})
В AngularJS предлагает 'фабрика('имя_службы', fnFactory)' метод, который принимает два параметра, ServiceName и функции JavaScript. Угловой создает экземпляр службы на вызов функции fnFactory() таких, как ниже.
var serviceInstace = fnFactory();
Переданную функцию можно определить объект и возвращает этот объект. AngularJS не просто сохраняет ссылку на этот объект в переменной, которая передается в качестве первого аргумента. Все, что возвращается из fnFactory будет привязан к serviceэкземпляр . Вместо того, чтобы возвращать объект , мы можем также возвратить функции, ценности и т. д., Что мы вернемся , будут доступны для экземпляра службы.
Пример:
var app= angular.module('myApp', []);
//creating service using factory method
app.factory('factoryPattern',function(){
var data={
'firstName':'Tom',
'lastName':' Cruise',
greet: function(){
console.log('hello!' + this.firstName + this.lastName);
}
};
//Now all the properties and methods of data object will be available in our service object
return data;
});
service('serviceName',function fnServiceConstructor(){})
Это'с другим способом, мы можем зарегистрировать службу. Единственная разница заключается в пути в AngularJS пытается инстанцировать объект обслуживания. На этот раз угловой использует 'новый' ключевое слово и вызовите конструктор функций что-то вроде ниже.
var serviceInstance = new fnServiceConstructor();
В функции конструктора мы можем использовать 'Это' сайта для добавления свойства/методы объекта обслуживания. пример:
//Creating a service using the service method
var app= angular.module('myApp', []);
app.service('servicePattern',function(){
this.firstName ='James';
this.lastName =' Bond';
this.greet = function(){
console.log('My Name is '+ this.firstName + this.lastName);
};
});
Поставщика (функции) является еще одним способом для создания сервисов. Давайте мы заинтересованы в том, чтобы создать сервис, который просто отображать приветственное сообщение для пользователя. Но мы также хотим, чтобы обеспечить такие функции, которые пользователь может установить свои собственные сообщения с приветствием. В техническом плане мы хотим создать настраиваемые службы. Как мы можем это сделать ? Там должен быть способ, так что приложение может передавать свои собственные поздравительные сообщения и AngularJS сделает его доступным для фабрики/функция-конструктор, которая может создать экземпляр служб. В таком случае поставщик() функция делает работу. через поставщика услуг (функций) мы можем создавать настраиваемые службы.
Мы можем создавать настраиваемые сервисы, используя синтаксис поставщику, как указано ниже.
/*step1:define a service */
app.provider('service',function serviceProviderConstructor(){});
/*step2:configure the service */
app.config(function configureService(serviceProvider){});
1.Объект создается с помощью функции конструктора, который мы определили в нашей функцией поставщиком.
var serviceProvider = new serviceProviderConstructor();
2.Функции мы прошли в приложение.конфиг(), выполнится. Это называется конфиг этап, и здесь у нас есть шанс настроить нашим сервисом.
configureService(serviceProvider);
3.Наконец, экземпляр службы создается путем вызова $get метод поставщику услуги.
serviceInstance = serviceProvider.$get()
var app= angular.module('myApp', []);
app.provider('providerPattern',function providerConstructor(){
//this function works as constructor function for provider
this.firstName = 'Arnold ';
this.lastName = ' Schwarzenegger' ;
this.greetMessage = ' Welcome, This is default Greeting Message' ;
//adding some method which we can call in app.config() function
this.setGreetMsg = function(msg){
if(msg){
this.greetMessage = msg ;
}
};
//We can also add a method which can change firstName and lastName
this.$get = function(){
var firstName = this.firstName;
var lastName = this.lastName ;
var greetMessage = this.greetMessage;
var data={
greet: function(){
console.log('hello, ' + firstName + lastName+'! '+ greetMessage);
}
};
return data ;
};
});
app.config(
function(providerPatternProvider){
providerPatternProvider.setGreetMsg(' How do you do ?');
}
);
[Рабочая Демо][2]
Фабрики использовать фабричную функцию, которая возвращает экземпляр сервиса. serviceэкземпляр = fnFactory();
Услуги используйте функцию-конструктор и угловые вызвать эту функцию конструктора с использованием 'новый' ключевое слово для создания экземпляра службы. serviceэкземпляр = новый fnServiceConstructor();
Провайдер определяет функцию providerConstructor, эта функция providerConstructor определяет функцию фабрики $вам . Угловые вызовы $получить() для создания объекта обслуживания. Синтаксис поставщик имеет дополнительное преимущество конфигурации объекта обслуживания до создания. serviceэкземпляр = $получить();
[1]: http://jsbin.com/vaken/16/edit?html этого JS,выход [2]: http://jsbin.com/senufu/6/edit?html этого JS,выход
Как указали несколько человек тут правильно фабрика, поставщик, услуги, и даже значение и постоянное версии то же самое. Вы можете вскрыть более общие "поставщик" на все из них. Вот так:
Здесь'ы статьи этот образ с:
<Н3>Фабрика</Н3>
Вы даете в AngularJS функция, в AngularJS будет кэшировать и ввести возвращаемое значение, когда завод просил.
Пример:
app.factory('factory', function() {
var name = '';
// Return value **is** the object that will be injected
return {
name: name;
}
})
Использование:
app.controller('ctrl', function($scope, factory) {
$scope.name = factory.name;
});
<Н3 и gt;Услуги</Н3>
Вы даете в AngularJS функция, AngularJS не буду называть новые, чтобы инстанцировать его. Это экземпляр, что AngularJS создает, что будет кэшироваться и вводят для запроса. С Новая, используемый для создания экземпляра сервиса сайта это является действующим и относится к экземпляру.
Пример:
app.service('service', function() {
var name = '';
this.setName = function(newName) {
name = newName;
}
this.getName = function() {
return name;
}
});
Использование:
app.controller('ctrl', function($scope, service) {
$scope.name = service.getName();
});
<Н3>поставщик</Н3>
Вы даете в AngularJS функция, и AngularJS будет называть его $вам функции. Это возвращаемое значение из функции
$вам` что будет кэшироваться и вкалывает, когда обслуживание не требуется.
Провайдеры позволяют настроить провайдер до автор называет `$вам метод для получения инъекций.
Пример:
app.provider('provider', function() {
var name = '';
this.setName = function(newName) {
name = newName;
}
this.$get = function() {
return {
name: name
}
}
})
Использование (как инъекций в контроллере)
app.controller('ctrl', function($scope, provider) {
$scope.name = provider.name;
});
Использование (настройки провайдера до$сделать называется создать для инъекций)
app.config(function(providerProvider) {
providerProvider.setName('John');
});
Играя с провайдерами, я заметил кое-что интересное.
Видимость инъекций для провайдеров отличается от видимости для сервисов и фабрик. Если вы объявляете в AngularJS "константу" (например, myApp.constant('a', 'Robert');
), вы можете вводить ее в сервисы, фабрики и провайдеры.
Но если вы объявите в AngularJS "значение" (например, myApp.value('b', {name: 'Jones'});
), вы можете внедрить его в сервисы и фабрики, но НЕ в функцию создания провайдера. Однако вы можете внедрить его в функцию $get
, которую вы определяете для своего провайдера. Это упоминается в документации AngularJS, но это легко пропустить. Вы можете найти его на странице %provide в разделах, посвященных методам value и constant.
<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>
Это очень запутанной частью для новичков, и я попытался прояснить это в простые слова
Услуги в AngularJS: используется для обмена служебной функции с справочная служба регулятора. Служба синглтон в природе, так что за одну услугу только один экземпляр создается в браузере и та же ссылка используется на всей странице.
На службе, мы создаем имена функций как собственность с этого объекта.
В AngularJS Фабрика: цель фабрики-это также же, как обслуживания, однако в данном случае мы создаем новый объект и добавить функции в качестве свойства этого объекта и в конце мы возвращаем этот объект.
В AngularJS поставщика: цели это опять же провайдер дает выход его'ы $вам функции.
Определение и использование сервиса, фабрики и поставщика описаны в http://www.dotnetfunda.com/articles/show/3156/difference-between-angularjs-service-factory-and-provider
Для меня самым лучшим и самым простым способом понимать разницу между:
var service, factory;
service = factory = function(injection) {}
Как AngularJS создает определенные компоненты (упрощенный):
// service
var angularService = new service(injection);
// factory
var angularFactory = factory(injection);
Так, для службы, что становится компонентом AngularJS-это экземпляр объекта класса, которое представлено объявление функции сервиса. Для завода, это результат, возвращаемый функцией фабрика декларации. Завод может вести себя так же, как и обслуживание:
var factoryAsService = function(injection) {
return new function(injection) {
// Service content
}
}
Простейший способ мышления заключается в следующем:
Фабрика 'класса' пример приведен в комментариях, а также разница поставщиком.
Мои разъяснения по этому вопросу:
В основном все из упомянутых типов (службы, фабрики, поставщик и т. д.) просто создание и настройка глобальных переменных (которые, конечно, глобальный для всего приложения), просто как старомодный глобальных переменных.
В то время как глобальные переменные не рекомендуется, реальное использование этих глобальных переменных, чтобы обеспечить внедрение зависимостей, путем передачи переменной к соответствующему контроллеру.
Есть много уровней сложности в создании ценности для "и глобальные переменные и":
. <БР/>то он должен иметь отдельный *$.сделать* функция, которая выполняется в AngularJS установив перечисленные свойства через приложение.файл config
, и этот $.вам функция ведет себя так же, как фабрика выше, в том, что ее возвращаемое значение используется для инициализации в "глобальном" и переменные. Мое понимание очень простое ниже.
Фабрики Вы просто создаете объект внутри завода и вернуть его.
Обслуживание:
У вас просто есть стандартная функция, которая использует это ключевое слово для определения функции.
Поставщик:
Есть `$получить объект, который вы определяете, и он может быть использован для получения объекта, который возвращает данные.
Резюме с угловые документов:
Лучшие ответы от так:
https://stackoverflow.com/a/26924234/165673 (<-- хорошее) https://stackoverflow.com/a/27263882/165673 https://stackoverflow.com/a/16566144/165673
Все уже хорошие ответы. Я хотел бы добавить еще несколько пунктов на обслуживание и завод. Наряду с разница между сервис/фабрика. И можно иметь такие вопросы, как:
Начнем с разницы между сервисом и заводом:
Оба одиночек: каждый раз, когда угловатые найти эти зависимости первый раз,это создать один экземпляр сервиса/фабрика. После того, как экземпляр создается, один и тот же экземпляр используется навсегда.
Можно использовать для моделирования объекта с поведением: они оба могут иметь методы, внутренние переменные состояния, и так далее. Хотя, как вы пишете, что код будет отличаться.
Услуги:
Служба-это функция-конструктор, и угловой будет инстанцировать его, вызывая новые yourServiceName()`. Это означает несколько вещей.
этого
.), он будет получать
этот` объект со всеми свойствами, которыми вы положили на нем.Образец Пример:
angular.service('MyService', function() {
this.aServiceVariable = "Ved Prakash"
this.aServiceMethod = function() {
return //code
};
});
когда угловые впрыскивает этого сервиса MyService С в контроллер, который от нее зависит, что контроллер получит
MyService С
, что он может вызвать функции, например, служба MyService.aServiceMethod ().
Будьте осторожны с этой
:
Так как построена служба-это объект, методы внутри он может относиться к этому, когда они называются:
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++;
};
});
Вы могли бы испытать желание назвать учетчик.setScore в цепочке объектов Promise, например, если вы инициализировали результат, захватывая его с сервера:
$протоколу HTTP.вам('/результат').затем(учетчик.setScore).Проблема в том, что учетчик.setScore
будет называться этой
обязан нуль
, и вы получите ошибки. Лучше бы $протоколу HTTP.вам('/результат').затем(учетчик.setScore.персонализация(учетчик))
.
Если вы решите воспользоваться этим в своих методах обслуживания или нет, будьте осторожны, как вы их называете.
Возвращает значение от услуг
:
Из-за как на JavaScript конструкторы работают, если вы вернетесь сложное значение (т. е. объект)
от конструктор
, звонящий вам вместо этого экземпляра этого объекта.
Это означает, что вы в принципе можете скопировать и вставить пример завод снизу, заменить фабрика
с Сервис
, и он будет работать:
angular.service('MyService', function($http) {
var api = {};
api.aServiceMethod= function() {
return $http.get('/users');
};
return api;
});
Поэтому, когда угловые конструкции вашего сервиса с новым MyService С(), он будет получать этот объект API вместо службы MyService экземпляр.
Это поведение для любого комплексного значения (объекты, функции), но не для примитивных типов.
Заводы:
Фабрика-это обычная функция, которая возвращает значение. Возвращаемое значение-это то, что вводится в вещи, которые зависят от завода. Типичная схема завода в угловатого возвращает объект функции в качестве свойства, как это:
angular.factory('MyFactory', function($http) {
var api = {};
api.aFactoryMethod= function() {
return $http.get('/users');
};
return api;
});
вводят значения для зависимостей фабрика возвращение завода ценность, и он не должен быть объектом. Это может быть функция
Ответы для 1 и 2 вопросы:
по большей части, просто палка с помощью фабрик за все. их поведение легче понять. Нет выбора о том, стоит ли возвращать или не возвращать значение, а кроме того, без багов будет внедрение, если вы делаете неправильную вещь.
Я по-прежнему называем их “услуг”, когда я говорю о инъекционных У них в зависимости, хотя.
обслуживание/поведение завод очень похож, а некоторые люди скажут что подойдет любой. Это отчасти правда, но мне легче следовать рекомендациям руководства по стилю Иоанна, папы и просто придерживаться заводы.**
Уже есть хорошие ответы, но я просто хочу поделиться этим.
В первую очередь: провайдер - способ/рецепт для создания обслуживание
(статический объект), который должен быть введен на $форсунки (как AngulaJS идет о шаблон МОК).
И значение, фабрики, обслуживание и постоянные (4 способа) - синтаксический сахар над провайдер путь/привести к появлению.
Есть Службы против завода часть была покрыта:
Обслуживание все о новый
ключевое слово на самом деле, как мы знаем, делает 4 вещи:
контекст
в этот
этот
И фабрики все о шаблона "Фабрика" - содержит функции, которые возвращают объекты подобного сервиса.
И эта простая/короткое видео: охватывает также поставщик:
(там вы видите, видите, как они идут с завода поставщика)Провайдер рецепт используется в основном в конфигурации приложения, пока приложение полностью загрузится/инициализации.
Дополнительные разъяснения заключается в том, что фабрики могут создать функции/примитивы, а услуг-нет. Проверить это [jsFiddle][1] на основе Epokk'ы:
.Фабрика возвращает функцию, которая может быть вызвана:
myApp.factory('helloWorldFromFactory', function() {
return function() {
return "Hello, World!";
};
});
Завод также может возвращать объект с методом, который может быть вызван:
myApp.factory('helloWorldFromFactory', function() {
return {
sayHello: function() {
return "Hello, World!";
}
};
});
Служба возвращает объект с методом, который может быть вызван:
myApp.service('helloWorldFromService', function() {
this.sayHello = function() {
return "Hello, World!";
};
});
Для получения более подробной информации, смотрите пост я писал о разнице: http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/
Прочитав все эти должности он создал более запутать для меня.. но все равно все это ценна информация.. наконец-то я нашел следующую таблицу, которая будет давать информацию с просто сравнение
И для новичка разобраться:- это не правильный вариант использования, но на высоком уровне это usecase для этих трех.
в
angular.module('myApp').config(function($testProvider){
$testProvider.someFunction();
})
в
Для основного Заводского сценарии&ампер;служба ведет себя так же.
Вот некоторые broilerplate код я'вэ придумали как код-шаблон для объекта завод на AngularJS. Я'вэ использовал автомобиль/CarFactory в качестве примера для иллюстрации. Делает для простой код реализации в контроллере.
<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>
Вот более простой пример. Я'м, используя несколько сторонних библиотек, которые ожидают, что "Положение" на предмет разоблачения широты и долготы, но с помощью различных свойств объекта. Я не'т хотите, чтобы взломать код поставщика, поэтому я поправил на "Положение" объекты я проходил рядом.
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
;