Я обнаружил, что все угловые термины были пугающими для начинающих. Мы начали с этой таблицы, которую нашим программистам было немного легче понять, изучая Angular demisx.github.io/angularjs/2014/09/14/… . Надеюсь, это тоже поможет вашей команде.
demisx
7
На мой взгляд, лучший способ понять разницу - это использовать собственную документацию Angular: docs.angularjs.org/guide/providers это очень хорошо объяснено и использует специфический пример, чтобы помочь вам понять это.
Рафаэль Мерлин
3
@ Blaise Спасибо! Согласно моему комментарию в посте, я умышленно исключил его, поскольку 99% случаев использования из моего опыта могут быть успешно обработаны с помощью service.factory. Не хотел усложнять эту тему дальше.
Из списка рассылки AngularJS я получил удивительную ветку, в которой объясняются сервисы против фабрики, против провайдеров и их использование. Составление ответов:
Сервисы
Синтаксис: module.service( 'serviceName', function );
Результат: при объявлении serviceName в качестве вводимого аргумента вам будет предоставлен экземпляр функции. Другими словамиnew FunctionYouPassedToService() .
Заводы
Синтаксис: module.factory( 'factoryName', function );
Результат: при объявлении factoryName в качестве вводимого аргумента вам будет предоставлено значение, возвращаемое путем вызова ссылки на функцию, переданной в module.factory .
Провайдеры
Синтаксис: module.provider( 'providerName', function );
Результат: При объявлении providerName в качестве вводимого аргумента вам будет предоставлено(new ProviderFunction()).$get() . Функция конструктора ProviderFunctionсоздается перед вызовом метода $ get - это ссылка на функцию, переданную в module.provider.
Преимущество провайдеров заключается в том, что их можно настраивать на этапе настройки модуля.
В редакторе 611 я добавил использование угловых констант и значений. Чтобы продемонстрировать отличия друг от друга, уже показано. jsbin.com/ohamub/611/edit
Этот пример может быть невероятным, если использовать четкий практический пример. Я теряюсь , пытаясь понять, в чем смысл вещей , как toEqualи greeter.Greetесть. Почему бы не использовать что-то более реальное и подходящее?
Кайл Пеннелл
5
Использование функции ожидаем () - плохой выбор, чтобы что-то объяснить. Используйте реальный код в следующий раз.
Пример "Hello world" с 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');});functionMyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService){
$scope.hellos =[
helloWorld.sayHello(),
helloWorldFromFactory.sayHello(),
helloWorldFromService.sayHello()];}
Не thisменяет контекст в $getфункции? - вы больше не обращаетесь к конкретному провайдеру в этой функции.
Нейт-Уилкинс,
12
@Nate: thisфактически не меняет контекст, потому что то, что вызывается, это new Provider(). $ Get (), где Providerпередается функция app.provider. Это значит, что он $get()вызывается как метод на построенном объекте Provider, поэтому мы thisбудем ссылаться на него, Providerкак показывает пример.
Брэндон
1
@ Брэндон Ох, ладно, тогда вроде как. Смущает на первый взгляд - спасибо за разъяснения!
Нейт-Уилкинс,
3
Почему я получаю Unknown provider: helloWorldProvider <- helloWorldпри запуске этого локально? Комментируя это, та же ошибка для двух других примеров. Есть ли какая-то скрытая конфигурация провайдера? (Angular 1.0.8) - Найдено: stackoverflow.com/questions/12339272/…
Антуан
4
Это причина, по которой @Antoine получает ошибку «Неизвестный провайдер: helloWorldProvider», потому что в вашем коде .config вы используете «helloWorldProvider», но когда вы определяете провайдера в myApp.provider («helloWorld», function ()), вы используете 'Привет мир'? Другими словами, как Angular узнает, что вы обращаетесь к провайдеру helloWorld? Спасибо
Jmtoung
645
TL; DR
1) Когда вы используете Factory, вы создаете объект, добавляете к нему свойства, а затем возвращаете тот же объект. Когда вы передадите эту фабрику в свой контроллер, эти свойства объекта теперь будут доступны в этом контроллере через вашу фабрику.
2) Когда вы используете Сервис , AngularJS создает его за кулисами с ключевым словом «new». Из-за этого вы добавите свойства в «this», и сервис вернет «this». Когда вы передаете услугу в свой контроллер, эти свойства в «this» теперь будут доступны на этом контроллере через ваш сервис.
3) Поставщики - это единственная услуга, которую вы можете передать в функцию .config (). Используйте провайдера, если вы хотите предоставить конфигурацию всего модуля для объекта службы, прежде чем сделать его доступным.
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 setin config’;});
Не TL; DR
1)
Фабрики - это самый популярный способ создания и настройки сервиса. Там действительно не намного больше, чем то, что сказал TL; DR. Вы просто создаете объект, добавляете к нему свойства, а затем возвращаете тот же объект. Затем, когда вы передадите фабрику в свой контроллер, эти свойства объекта теперь будут доступны в этом контроллере через вашу фабрику. Более подробный пример приведен ниже.
app.factory(‘myFactory’,function(){var service ={};return service;});
Теперь любые свойства, которые мы прикрепляем к «сервису», будут нам доступны, когда мы передадим «myFactory» в наш контроллер.
Теперь давайте добавим некоторые «приватные» переменные в нашу функцию обратного вызова. Они не будут напрямую доступны из контроллера, но мы в конечном итоге настроим некоторые методы получения / установки для «службы», чтобы иметь возможность изменять эти «частные» переменные при необходимости.
Здесь вы заметите, что мы не привязываем эти переменные / функцию к 'service'. Мы просто создаем их, чтобы потом использовать или модифицировать их.
baseUrl - это базовый URL, который требуется iTunes API
_artist - художник, которого мы хотим найти
_finalUrl - это окончательный и полностью созданный URL, по которому мы сделаем звонок в iTunes.
makeUrl - это функция, которая создает и возвращает наш удобный для iTunes URL.
Теперь, когда наши вспомогательные / закрытые переменные и функции на месте, давайте добавим некоторые свойства к объекту 'service'. Все, что мы ставим на «сервис», можно напрямую использовать внутри любого контроллера, в который мы передаем «myFactory».
Мы собираемся создать методы setArtist и getArtist, которые просто возвращают или устанавливают художника. Мы также собираемся создать метод, который будет вызывать iTunes API с нашим созданным URL. Этот метод возвращает обещание, которое будет выполнено, как только данные вернутся из iTunes API. Если у вас не было большого опыта использования обещаний в AngularJS, я настоятельно рекомендую глубоко погрузиться в них.
Ниже setArtist принимает художника и позволяет установить художника. getArtist возвращает художника. callItunes сначала вызывает makeUrl (), чтобы создать URL, который мы будем использовать с нашим запросом $ http. Затем он устанавливает объект обещания, делает запрос $ http с нашим окончательным URL, а затем, так как $ http возвращает обещание, мы можем вызвать .success или .error после нашего запроса. Затем мы выполняем наше обещание с помощью данных iTunes или отклоняем его с сообщением «Произошла ошибка».
Теперь наша фабрика завершена. Теперь мы можем внедрить 'myFactory' в любой контроллер, и тогда мы сможем вызывать наши методы, которые мы прикрепили к нашему сервисному объекту (setArtist, getArtist и callItunes).
В контроллере выше мы вводим в сервис «myFactory». Затем мы устанавливаем свойства нашего объекта $ scope с данными из myFactory. Единственный сложный код выше, если вы никогда не имели дело с обещаниями раньше. Поскольку callItunes возвращает обещание, мы можем использовать метод .then () и устанавливать $ scope.data.artistData только после того, как наше обещание будет выполнено с данными iTunes. Вы заметите, что наш контроллер очень «тонкий» (это хорошая практика кодирования). Вся наша логика и постоянные данные находятся в нашем сервисе, а не в нашем контроллере.
2) Сервис
Возможно, самая важная вещь, которую нужно знать при создании Сервиса, это то, что он создается с ключевым словом «new». Для вас, гуру JavaScript, это должно дать вам подсказку о природе кода. Для тех из вас, кто имеет ограниченный опыт работы с JavaScript, или тех, кто не слишком знаком с тем, что на самом деле делает ключевое слово «new», давайте рассмотрим некоторые основы JavaScript, которые в конечном итоге помогут нам понять природу Сервиса.
Чтобы действительно увидеть изменения, которые происходят при вызове функции с ключевым словом «new», давайте создадим функцию и вызовем ее с ключевым словом «new», а затем покажем, что делает интерпретатор, когда видит ключевое слово «new». Конечные результаты будут одинаковыми.
Это типичная функция конструктора JavaScript. Теперь всякий раз, когда мы вызываем функцию Person с помощью ключевого слова new, this будет привязано к вновь созданному объекту.
Теперь давайте добавим метод в прототип нашего Person, чтобы он был доступен для каждого экземпляра нашего класса Person.
Person.prototype.sayName =function(){
alert(‘My name is‘+this.name);}
Теперь, поскольку мы поместили функцию sayName в прототип, каждый экземпляр Person сможет вызывать функцию sayName в порядке оповещения об имени этого экземпляра.
Теперь, когда у нас есть функция конструктора Person и наша функция sayName в ее прототипе, давайте создадим экземпляр Person, а затем вызовем функцию sayName.
var tyler =newPerson(‘Tyler’,23);
tyler.sayName();//alerts ‘My name is Tyler’
Таким образом, весь код для создания конструктора Person, добавления функции к его прототипу, создания экземпляра Person и последующего вызова функции для его прототипа выглядит следующим образом.
varPerson=function(name, age){this.name = name;this.age = age;}Person.prototype.sayName =function(){
alert(‘My name is‘+this.name);}var tyler =newPerson(‘Tyler’,23);
tyler.sayName();//alerts ‘My name is Tyler’
Теперь давайте посмотрим, что на самом деле происходит, когда вы используете ключевое слово «new» в JavaScript. Первое, что вы должны заметить, это то, что после использования «new» в нашем примере мы можем вызвать метод (sayName) для «tyler» так же, как если бы это был объект - так оно и есть. Итак, во-первых, мы знаем, что наш конструктор Person возвращает объект, видим ли мы это в коде или нет. Во-вторых, мы знаем, что поскольку наша функция sayName расположена в прототипе, а не непосредственно в экземпляре Person, объект, который возвращает функция Person, должен делегировать своему прототипу при неудачных поисках. Проще говоря, когда мы вызываем tyler.sayName (), интерпретатор говорит: «Хорошо, я собираюсь посмотреть на только что созданный объект« tyler », найти функцию sayName, а затем вызвать ее. Подожди, я не вижу этого здесь - все, что я вижу, это имя и возраст, позвольте мне проверить прототип. Да, похоже, что это на прототипе, позвольте мне назвать это ».
Ниже приведен код того, как вы можете думать о том, что на самом деле делает ключевое слово «новый» в JavaScript. Это в основном пример кода вышеупомянутого абзаца. Я поместил «представление интерпретатора» или то, как интерпретатор видит код внутри заметок.
varPerson=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». Объединяя эти знания с нашими примерами выше, вы теперь должны понимать, что вы будете привязывать свои свойства и методы непосредственно к «this», которое затем будет возвращено из самой Службы. Давайте посмотрим на это в действии.
В отличие от того, что мы изначально делали с примером Factory, нам не нужно создавать объект, а затем возвращать этот объект, потому что, как упоминалось много раз ранее, мы использовали ключевое слово «new», поэтому интерпретатор создаст этот объект, предоставив ему делегирование это прототип, а затем верните его нам без необходимости выполнять работу.
Прежде всего, давайте создадим нашу «приватную» и вспомогательную функцию. Это должно выглядеть очень знакомо, так как мы сделали то же самое с нашим заводом. Я не буду объяснять, что здесь делает каждая строка, потому что я сделал это в заводском примере, если вы не уверены, перечитайте заводской пример.
Теперь, как и на нашей фабрике, setArtist, getArtist и callItunes будут доступны в любом контроллере, в который мы передаем myService. Вот контроллер myService (который почти такой же, как наш заводской контроллер).
Как я уже упоминал ранее, когда вы действительно понимаете, что делает «новое», Сервисы практически идентичны фабрикам в AngularJS.
3) Провайдер
Самое важное, что нужно помнить о провайдерах, это то, что они являются единственной службой, которую вы можете передать в часть app.config вашего приложения. Это имеет огромное значение, если вам нужно изменить какую-то часть вашего сервисного объекта, прежде чем он станет доступен везде в вашем приложении. Хотя это очень похоже на Услуги / Фабрики, есть несколько различий, которые мы обсудим.
Сначала мы настраиваем нашего провайдера аналогично тому, как мы работали с нашим сервисом и фабрикой. Переменные ниже являются нашей «приватной» и вспомогательной функцией.
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;}}
* Опять же, если какая-либо часть приведенного выше кода вводит в заблуждение, ознакомьтесь с разделом «Фабрика», где я объясняю, для чего все это более подробно.
Вы можете думать о провайдерах как о трех разделах. Первый раздел - это «частные» переменные / функции, которые будут изменены / установлены позже (показано выше). Второй раздел - это переменные / функции, которые будут доступны в вашей функции app.config и, следовательно, доступны для изменения до того, как они станут доступны где-либо еще (также показано выше). Важно отметить, что эти переменные должны быть присоединены к ключевому слову this. В нашем примере, только 'thingFromConfig' будет доступен для изменения в app.config. Третий раздел (показанный ниже) - это все переменные / функции, которые будут доступны в вашем контроллере, когда вы передадите службу myProvider в этот конкретный контроллер.
При создании службы с помощью Provider в вашем контроллере будут доступны только те свойства / методы, которые возвращаются из функции $ get (). Приведенный ниже код помещает $ get в this (которое, как мы знаем, будет возвращено из этой функции). Теперь эта функция $ get возвращает все методы / свойства, которые мы хотим быть доступными в контроллере. Вот пример кода.
Теперь полный код провайдера выглядит следующим образом
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 belowthis.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
}}});
Теперь, как и на нашей фабрике, Service, setArtist, getArtist и callItunes будут доступны в любом контроллере, в который мы передаем myProvider. Вот контроллер myProvider (который почти такой же, как наш заводской / сервисный контроллер).
Как упоминалось ранее, весь смысл создания службы с помощью Provider заключается в возможности изменять некоторые переменные с помощью функции app.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' является пустой строкой в нашем провайдере, но когда это появится в DOM, это будет "Это предложение было установлено ...".
Единственная часть, которая отсутствует в этой превосходной статье, - это относительные преимущества использования сервиса над фабрикой; что ясно объясняется в принятом ответе Лиора
Изюминка «JavaScript-гуру» была хитрой. : D Думаю, этот ответ очень многое прояснит. Великолепно написано.
Амармишра
4
Вашему TLDR нужен TLDR.
JensB
3
@JensB tl; dr - Learn React.
Тайлер Макгиннис
512
Все Сервисы являются одиночными ; они создаются один раз за приложение. Они могут быть любого типа , будь то примитив, литерал объекта, функция или даже экземпляр пользовательского типа.
value, factory, service, constant, И providerметоды все провайдеры. Они учат Инжектора, как создавать Услуги.
Наиболее многословным, но и наиболее полным является рецепт провайдера. В остальных четырех типов рецептов - Value, фабрика, Обслуживание и Constant - это просто синтаксический сахар поверх рецепта поставщика .
Рецепт Value является наиболее простым случаем, когда вы создаете экземпляр сервиса самостоятельно и предоставить конкретизированное значение для инжектора.
Рецепт Фабрика дает Инжектор функцию заводскую , что он вызывает , когда необходимо создать экземпляр службы. При вызове фабричная функция создает и возвращает экземпляр службы. Зависимости Сервиса вводятся как аргументы функций. Поэтому использование этого рецепта добавляет следующие способности:
Возможность использования других сервисов (есть зависимости)
Служба инициализации
Отложенная / ленивая инициализация
Рецепт Сервиса почти такие же , как рецепт фабрики, но здесь Injector вызывает конструктор с новым оператором вместо функции фабрики.
Рецепт поставщика , как правило , избыточен . Он добавляет еще один уровень косвенности, позволяя настроить создание фабрики.
Вы должны использовать рецепт провайдера только в том случае, если вы хотите предоставить API для конфигурации всего приложения, которую необходимо выполнить до запуска приложения. Обычно это интересно только для многоразовых сервисов, чье поведение может немного отличаться в разных приложениях.
Constant рецепт просто как рецепт Значение кроме этого позволяет определить услуги, которые доступны в конфигурации фазы. Раньше, чем сервисы, созданные с использованием рецепта Value. В отличие от значений, они не могут быть оформлены с использованием decorator.
Значит сервис и фабрика по сути одинаковы? Использование одного другого обеспечивает ничего, кроме альтернативного синтаксиса?
Мэтт
2
@ Матт, да, сервис - это лаконичный способ, когда у вас уже есть собственная функция, которую вы хотите представить как сервис. Из документов: myApp.factory ('unicornLauncher', ["apiToken", function (apiToken) {вернуть новый UnicornLauncher (apiToken);}]); vs: myApp.service ('unicornLauncher', ["apiToken", UnicornLauncher]);
Янв
5
@joshperry Как новичок, я некоторое время гуглял разницу между сервисом и фабрикой. Я согласен, что это лучший ответ! Я бы понял службу как класс службы (например, класс кодировщика / декодера), который может иметь некоторые частные свойства. И фабрика предоставляет набор вспомогательных методов без сохранения состояния.
stanleyxu2005
3
Примеры Yaa в других ответах, приведенных выше, не очень четко объясняют основное различие между ч / б услугами и провайдерами, которое и вводится в то время, когда создаются эти рецепты.
Ашиш Сингх
223
Понимание AngularJS Factory, Сервис и Поставщик
Все они используются для совместного использования одноразовых объектов. Это помогает обмениваться повторно используемым кодом через ваше приложение / различные компоненты / модули.
Ленивый экземпляр - Angular создает экземпляр сервиса / фабрики только тогда, когда от него зависит компонент приложения.
Singletons - каждый компонент, зависящий от сервиса, получает ссылку на один экземпляр, сгенерированный фабрикой сервисов.
завод
Фабрика - это функция, в которой вы можете манипулировать / добавлять логику перед созданием объекта, после чего возвращается вновь созданный объект.
app.factory('MyFactory',function(){var serviceObj ={};//creating an object with methods/functions or variables
serviceObj.myFunction =function(){//TO DO:};//return that objectreturn serviceObj;});
Применение
Это может быть просто набор функций, таких как класс. Следовательно, он может быть создан в разных контроллерах, когда вы вводите его в функции контроллера / фабрики / директивы. Он создается только один раз за приложение.
обслуживание
Просто, глядя на сервисы, подумайте о прототипе массива. Служба - это функция, которая создает новый объект, используя ключевое слово «new». Вы можете добавить свойства и функции к объекту службы, используя thisключевое слово. В отличие от фабрики, он ничего не возвращает (он возвращает объект, который содержит методы / свойства).
app.service('MyService',function(){//directly binding events to this contextthis.myServiceFunction =function(){//TO DO:};});
Применение
Используйте его, когда вам нужно поделиться одним объектом по всему приложению. Например, данные пользователя, прошедшего проверку подлинности, методы / данные для совместного использования, функции служебных программ и т. Д.
поставщик
Поставщик используется для создания настраиваемого объекта службы. Вы можете настроить параметры сервиса из функции конфигурации. Возвращает значение с помощью $get()функции. $getФункция запускается на выполнение на этапе выполнения в угловой.
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 на основе вашей среды, например dev, stageилиprod
НОТА
Только поставщик будет доступен в фазе конфигурации angular, а сервис и фабрика - нет.
Надеюсь, что это прояснило ваше понимание о фабрике, обслуживании и поставщике .
Что бы я сделал, если бы я хотел иметь службу с определенным интерфейсом, но иметь две разные реализации и внедрять каждую в контроллер, но привязывать к различным состояниям с помощью ui-router? например, делать удаленные вызовы в одном состоянии, но вместо этого записывать в локальное хранилище. Документы провайдера говорят, чтобы использовать only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications, так что не кажется возможным, верно?
9
191
Для меня откровение пришло, когда я понял, что все они работают одинаково: запустив что-то один раз , сохранив полученное значение, а затем обработайте то же самое сохраненное значение, когда на него ссылаются посредством внедрения зависимостей .
cХранимое значение приходит от первого получения экземпляра с помощью newing fn, а затем запуска $getметода экземпляра.
Это означает, что внутри AngularJS есть что-то вроде объекта кеша, значение которого для каждой инъекции присваивается только один раз, когда они были введены впервые, и где:
Мне также нравится этот ответ больше всего. Смысл всех их заключается в предоставлении доступа к объекту при необходимости через DI. Обычно у вас все хорошо с factoryс. Единственная причина serviceсуществования - это языки, такие как CoffeeScript, TypeScript, ES6 и т. Д., Поэтому вы можете использовать синтаксис их классов. Вам нужны providers, только если ваш модуль используется в нескольких приложениях с разными настройками при помощи app.config(). Если ваш сервис является чисто одноэлементным или способен создавать экземпляры чего-либо, зависит только от вашей реализации.
Андреас Линнерт
137
Сервис против провайдера против фабрики:
Я пытаюсь сделать это простым. Это все о базовой концепции JavaScript.
Прежде всего, давайте поговорим об услугах в AngularJS!
Что такое Сервис:
В AngularJS, Сервисэто не что иное, как одиночный объект JavaScript, который может хранить некоторые полезные методы или свойства. Этот одноэлементный объект создается на основе ngApp (приложение Angular) и используется всеми контроллерами в текущем приложении. Когда Angularjs создает объект службы, он регистрирует этот объект службы с уникальным именем службы. Поэтому каждый раз, когда нам нужен экземпляр службы, Angular ищет в реестре это имя службы и возвращает ссылку на объект службы. Таким образом, мы можем вызвать метод, получить доступ к свойствам и т. Д. На объекте службы. У вас может возникнуть вопрос, можете ли вы также поместить свойства, методы в объектную область контроллеров! Так зачем вам сервисный объект? Ответы таковы: сервисы распределяются между несколькими контроллерами. Если вы поместите некоторые свойства / методы в объект области видимости контроллера, он будет доступен только для текущей области видимости.
Таким образом, если существует три области контроллера, пусть это будут controllerA, controllerB и controllerC, все они будут использовать один и тот же экземпляр службы.
AngularJS предоставляет метод factory ('serviceName', fnFactory) ', который принимает два параметра, serviceName и функцию JavaScript. Angular создает экземпляр службы, вызывая функцию fnFactory (), например ниже.
var serviceInstace = fnFactory();
Переданная функция может определить объект и вернуть этот объект. AngularJS просто сохраняет эту ссылку на объект в переменную, которая передается в качестве первого аргумента. Все, что возвращается из fnFactory, будет связано с serviceInstance. Вместо того, чтобы возвращать объект, мы также можем возвращать функцию, значения и т. Д. Что бы мы ни возвращали, они будут доступны экземпляру службы.
Пример:
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 objectreturn data;});
Это еще один способ, мы можем зарегистрировать услугу. Единственное отличие состоит в том, как AngularJS пытается создать экземпляр объекта службы. На этот раз angular использует ключевое слово «new» и вызывает функцию конструктора, как показано ниже.
var serviceInstance =new fnServiceConstructor();
В функции конструктора мы можем использовать ключевое слово this для добавления свойств / методов к объекту службы. пример:
//Creating a service using the service methodvar 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);};});
Функция провайдера:
Функция Provider () - это еще один способ создания сервисов. Пусть нам интересно создать сервис, который просто отображает какое-то приветственное сообщение пользователю. Но мы также хотим предоставить такую функциональность, чтобы пользователь мог установить собственное приветственное сообщение. В техническом плане мы хотим создавать настраиваемые сервисы. Как мы можем это сделать ? Должен быть способ, чтобы приложение могло передавать свои пользовательские приветственные сообщения, а Angularjs делал бы его доступным для функции фабрики / конструктора, которая создает наш экземпляр сервисов. В таком случае функция provider () выполняет свою работу. используя функцию provider (), мы можем создавать настраиваемые сервисы.
Мы можем создавать настраиваемые сервисы, используя синтаксис провайдера, как указано ниже.
/*step1:define a service */
app.provider('service',function serviceProviderConstructor(){});/*step2:configure the service */
app.config(function configureService(serviceProvider){});
Как работает синтаксис провайдера?
1.Provider объект создается с помощью функции конструктора, которую мы определили в нашей функции провайдера.
var serviceProvider =new serviceProviderConstructor();
2. Функция, которую мы передали в app.config (), выполняется. Это называется этапом конфигурации, и здесь у нас есть возможность настроить наш сервис.
configureService(serviceProvider);
3. Наконец, экземпляр службы создается путем вызова $ get метода serviceProvider.
serviceInstance = serviceProvider.$get()
Пример кода для создания сервиса с использованием синтаксиса:
var app= angular.module('myApp',[]);
app.provider('providerPattern',function providerConstructor(){//this function works as constructor function for providerthis.firstName ='Arnold ';this.lastName =' Schwarzenegger';this.greetMessage =' Welcome, This is default Greeting Message';//adding some method which we can call in app.config() functionthis.setGreetMsg =function(msg){if(msg){this.greetMessage = msg ;}};//We can also add a method which can change firstName and lastNamethis.$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 ?');});
Фабрика использует фабричную функцию, которая возвращает экземпляр службы.
serviceInstance = fnFactory ();
Сервис использует функцию конструктора, и Angular вызывает эту функцию конструктора, используя ключевое слово «new» для создания экземпляра сервиса.
serviceInstance = new fnServiceConstructor ();
Provider определяет функцию providerConstructor, эта функция providerConstructor определяет фабричную функцию $ get . Angular вызывает $ get () для создания объекта службы. Синтаксис провайдера имеет дополнительное преимущество в настройке объекта службы перед его созданием.
serviceInstance = $ get ();
Как правильно отметили несколько человек, фабрика, поставщик, сервис и даже значение и константа являются версиями одного и того же. Вы можете разбить более общее providerна всех из них. Вот так:
Вы даете AngularJS функцию, AngularJS вызовет new, чтобы создать ее экземпляр. Это экземпляр, который создает AngularJS, который будет кэшироваться и вставляться при запросе сервиса. Поскольку new использовался для создания экземпляра службы, ключевое слово this является действительным и относится к экземпляру.
Пример:
app.service('service',function(){var name ='';this.setName =function(newName){
name = newName;}this.getName =function(){return name;}});
Вы даете AngularJS функцию, а AngularJS будет вызывать ее $getфункцию. Это возвращаемое значение из $getфункции, которая будет кэшироваться и вставляться при запросе службы.
Провайдеры позволяют вам настроить провайдера до того, как AngularJS $getвызовет метод, чтобы получить инъекцию.
Пример:
app.provider('provider',function(){var name ='';this.setName =function(newName){
name = newName;}this.$get =function(){return{
name: name
}}})
Я заметил кое-что интересное, играя с провайдерами.
Видимость инъекционных препаратов различна для поставщиков, чем для служб и предприятий. Если вы объявите AngularJS «константой» (например, myApp.constant('a', 'Robert');), вы можете внедрить его в службы, фабрики и поставщиков.
Но если вы объявите AngularJS «значение» (например,. myApp.value('b', {name: 'Jones'});), Вы можете внедрить его в службы и фабрики, но НЕ в функцию создания провайдера. Однако вы можете добавить его в $getфункцию, определенную для вашего провайдера. Это упоминается в документации AngularJS, но это легко пропустить. Вы можете найти его на странице% provide в разделах о методах value и constant.
Это очень запутанная часть для новичка, и я попытался объяснить это простыми словами
Служба AngularJS: используется для совместного использования служебных функций со ссылкой на службу в контроллере. Служба является одноэлементной по своей природе, поэтому для одного сервиса в браузере создается только один экземпляр, и одна и та же ссылка используется на всей странице.
В сервисе мы создаем имена функций как свойства этого объекта.
AngularJS Factory: назначение Factory также совпадает с Service, однако в этом случае мы создаем новый объект и добавляем функции в качестве свойств этого объекта, а в конце возвращаем этот объект.
Поставщик AngularJS: цель этого снова та же, однако поставщик предоставляет вывод своей функции $ get.
Таким образом, для службы то, что становится компонентом AngularJS, является экземпляром объекта класса, который представлен функцией объявления службы. Для фабрики это результат, возвращаемый функцией объявления фабрики. Фабрика может вести себя так же, как сервис:
var factoryAsService =function(injection){returnnewfunction(injection){// Service content}}
Самый простой способ мышления следующий:
Сервис - это экземпляр объекта-одиночки. Используйте сервисы, если вы хотите предоставить одноэлементный объект для вашего кода.
Фабрика это класс. Используйте фабрики, если вы хотите предоставить собственные классы для своего кода (это невозможно сделать с помощью сервисов, потому что они уже созданы).
Пример фабричного «класса» приведен в комментариях, а также о разнице поставщиков.
как сервис может быть одноэлементным, если он создается каждый раз при использовании? я могу обдумать это ...
Джо
Служба создается только один раз во время разрешения зависимости, и затем, когда вы запрашиваете службу у инжектора, вы всегда получаете один и тот же экземпляр. Это можно легко проверить здесь: jsfiddle.net/l0co/sovtu55t/1 , пожалуйста, запустите его с консоли. Консоль показывает, что служба создается только один раз.
Лукаш Франковски
а ну понятно. Я ожидал, что смогу буквально new MyService()или что-то :)
Джо
33
Мои разъяснения по этому вопросу:
В основном все упомянутые типы (сервис, фабрика, поставщик и т. Д.) Просто создают и настраивают глобальные переменные (которые, конечно, являются глобальными для всего приложения), как это делали устаревшие глобальные переменные.
Хотя глобальные переменные не рекомендуются, реальное использование этих глобальных переменных заключается в обеспечении внедрения зависимостей путем передачи переменной соответствующему контроллеру.
Существует много уровней сложности при создании значений для «глобальных переменных»:
Константа
Это определяет фактическую константу, которая не должна изменяться в течение всего приложения, так же как и константы в других языках (чего нет в JavaScript).
Значение
Это изменяемое значение или объект, и он служит некоторой глобальной переменной, которую можно даже внедрить при создании других служб или фабрик (см. Далее). Тем не менее, это должно быть « буквальное значение », что означает, что нужно выписать фактическое значение и не может использовать какую-либо логику вычислений или программирования (другими словами, 39 или myText или {prop: «value»} в порядке, но 2 +2 нет).
Фабрика
Более общее значение, которое можно вычислить сразу. Он работает путем передачи функции в AngularJS с логикой, необходимой для вычисления значения, и AngularJS выполняет ее, и сохраняет возвращаемое значение в именованной переменной.
Обратите внимание, что можно вернуть объект (в этом случае он будет функционировать аналогично службе ) или функцию (которая будет сохранена в переменной как функция обратного вызова).
Служба
Служба - это более урезанная версия фабрики, которая действует только тогда, когда значение является объектом, и она позволяет писать любую логику непосредственно в функции (как если бы она была конструктором), а также объявлять и получать доступ свойства объекта с использованием этого ключевого слова.
Провайдер
В отличие от сервиса, который является упрощенной версией фабрики , провайдер является более сложным, но более гибким способом инициализации «глобальных» переменных, при этом наибольшей гибкостью является возможность установки значений из app.config.
Это работает как использование комбинации службы и поставщика , передавая поставщику функцию, свойства которой объявлены с использованием ключевого слова this , которое можно использовать из app.config.
Затем он должен иметь отдельную функцию $ .get, которая выполняется AngularJS после установки указанных выше свойств через app.configфайл, и эта функция $ .get ведет себя так же, как фабрика выше, тем, что его возвращаемое значение используется для инициализации «глобальных» переменных.
Разве вы не перепутали Фабрику и Сервис? Служба создает, где фабрика возвращается.
Флавиен Волкен
Когда вы объявляете имя службы как вводимый аргумент, вам будет предоставлен экземпляр функции. Другими словами, новый FunctionYouPassedToService (). Этот экземпляр объекта становится сервисным объектом, который AngularJS регистрирует и затем внедряет в другие сервисы / контроллеры, если это необходимо. // factory Когда вы объявляете factoryname как вводимый аргумент, вам будет предоставлено значение, возвращаемое путем вызова ссылки на функцию, переданной в module.factory.
Саджан
Хорошо, так что ... в угловом виде фабрика - это синглтон, где "сервис" - это фактически фабрика (в общих чертах дизайна)
Фабрика и Сервис - наиболее часто используемые рецепты. Единственная разница между ними состоит в том, что рецепт Service лучше работает для объектов пользовательского типа, тогда как Factory может создавать примитивы и функции JavaScript.
Provider рецепт является основной тип рецепт и все остальные просто синтаксический сахар на нем.
Поставщик - самый сложный тип рецепта. Вам это не нужно, если вы не создаете многократно используемый код, который нуждается в глобальной настройке.
Все хорошие ответы уже. Я хотел бы добавить еще несколько пунктов на Сервис и Фабрика . Вместе с разницей между сервисом / фабрикой. И можно также иметь такие вопросы, как:
Должен ли я использовать сервис или завод? Какая разница?
Они делают то же самое или ведут себя одинаково?
Давайте начнем с разницы между обслуживанием и фабрикой:
Оба являются синглетонами : всякий раз, когда Angular находит их как зависимость в первый раз, он создает один экземпляр сервиса / фабрики. Как только экземпляр создан, тот же экземпляр используется навсегда.
Может использоваться для моделирования объекта с поведением : у них могут быть методы, внутренние переменные состояния и т. Д. Хотя способ написания этого кода будет отличаться.
Сервисы:
Сервис - это функция конструктора, и Angular создаст его экземпляр, вызвав new yourServiceName(). Это означает пару вещей.
Функции и переменные экземпляра будут свойствами this.
Вам не нужно возвращать значение. Когда Angular вызывает new yourServiceName(), он получит thisобъект со всеми свойствами, которые вы на него наделили.
Когда Angular внедряет этот MyServiceсервис в контроллер, который зависит от него, этот контроллер получит объект MyService, для которого он может вызывать функции, например MyService.aServiceMethod ().
Будьте осторожны сthis :
Поскольку созданный сервис является объектом, методы внутри него могут ссылаться на него при вызове:
У вас может возникнуть соблазн вызвать ScoreKeeper.setScoreцепочку обещаний, например, если вы инициализировали счет, взяв его с сервера: $http.get('/score').then(ScoreKeeper.setScore).проблема в том, что ScoreKeeper.setScoreон будет вызван с thisпривязкой к, nullи вы получите ошибки. Лучший способ был бы $http.get('/score').then(ScoreKeeper.setScore.bind(ScoreKeeper)). Если вы решите использовать это в своих методах обслуживания или нет, будьте осторожны, как вы их называете.
Возврат значения изService :
Из-за того, как работают конструкторы JavaScript, если вы возвращаете комплексное значение (i.e., an Object)из constructorфункции, вызывающая сторона получит этот объект вместо этого экземпляра.
Это означает, что вы можете скопировать и вставить заводской пример снизу, заменить factoryна service, и он будет работать:
angular.service('MyService',function($http){var api ={};
api.aServiceMethod=function(){return $http.get('/users');};return api;});
Поэтому, когда Angular создает ваш сервис с новым MyService (), он получает этот объект API вместо экземпляра MyService.
Это поведение для любых сложных значений (объектов, функций), но не для примитивных типов.
Заводы:
Фабрика - это простая старая функция, которая возвращает значение. Возвращаемое значение - это то, что вводится в вещи, которые зависят от фабрики. Типичный шаблон фабрики в Angular - возвращать объект с функциями в качестве свойств, например так:
angular.factory('MyFactory',function($http){var api ={};
api.aFactoryMethod=function(){return $http.get('/users');};return api;});
Введенное значение для фабричной зависимости - это возвращаемое фабрикой значение, и оно не обязательно должно быть объектом. Это может быть функцией
Ответы на вопросы 1 и 2 выше:
По большей части, просто используйте фабрики для всего. Их поведение легче понять. Нет никакого выбора, возвращать ли значение или нет, и, кроме того, нет ошибок, если вы поступите неправильно.
Однако я все еще называю их «услугами», когда говорю о внедрении их как зависимостей.
Поведение Service / Factory очень похоже, и некоторые люди скажут, что любой из них в порядке. Это несколько верно, но мне легче следовать советам руководства по стилю Джона Папы и просто придерживаться заводов. **
Уже есть хорошие ответы, но я просто хочу поделиться этим.
Прежде всего: Provider - это способ / рецепт для создания service(одноэлементного объекта), который должен быть введен $ инжектором (как AngulaJS использует шаблон IoC).
И Value, Factory, Service и Constant (4 способа) - синтаксический сахар по сравнению с Provider way / recepie.
Сервис - это все о newключевом слове, которое, как мы знаем, делает 4 вещи:
создает новый объект
связывает его с его prototypeобъектом
подключается contextкthis
и возвращается this
А Factory - это все о Factory Pattern - содержит функции, которые возвращают объекты, подобные этой службе.
возможность использования других сервисов (есть зависимости)
инициализация сервиса
отложенная / ленивая инициализация
И это простое / короткое видео: охватывает также провайдера : https://www.youtube.com/watch?v=HvTZbQ_hUZY (там, на котором вы видите, видно, как они идут от фабрики к провайдеру)
Рецепт провайдера используется в основном в конфигурации приложения до того, как приложение полностью запустится / инициализируется.
После прочтения всех этих постов это создало больше путаницы для меня .. Но все же все это является полезной информацией .. наконец я нашел следующую таблицу, которая даст информацию с простым сравнением
Инжектор использует рецепты для создания двух типов объектов: сервисов и объектов специального назначения.
Существует пять типов рецептов, которые определяют, как создавать объекты: Value, Factory, Service, Provider и Constant.
Фабрика и Сервис - наиболее часто используемые рецепты. Единственная разница между ними состоит в том, что рецепт Service лучше работает для объектов пользовательского типа, тогда как Factory может создавать примитивы и функции JavaScript.
Рецепт провайдера является основным типом рецепта, а все остальные - просто синтаксический сахар.
Поставщик - самый сложный тип рецепта. Вам это не нужно, если вы не создаете многократно используемый код, который нуждается в глобальной настройке.
Все объекты специального назначения, кроме Контроллера, определяются с помощью заводских рецептов.
И для начинающего понять: - Это может не исправить вариант использования, но на высоком уровне это то, что сценарий использования для этих трех.
Если вы хотите использовать в модуле конфигурации угловой модуль должен быть создан в качестве поставщика
Вот пример кода, который я придумал как шаблон кода для фабрики объектов в AngularjS. Я использовал Car / 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 inif(value ===undefined){// and a default value was specifiedif(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)returnthis;};// end this.set()};// end this.Car class definition// instance properties default valuesthis.Car.prototype.defaults ={
color:'yellow',
numberOfDoors:2,
hasLeatherSeats:null,
hasFancyRadio:false};// instance factory method / constructorthis.Car.prototype.instance =function(params){returnnewthis.constructor().set('color', params.color).set('numberOfDoors', params.numberOfDoors).set('hasFancyRadio', params.hasFancyRadio).set('hasLeatherSeats', params.hasLeatherSeats);};returnnewthis.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;returnthis;};this.setLongitude =function(longitude){this.longitude = longitude;this.lon = longitude;this.coords.longitude = longitude;returnthis;};};// end class definition// instance factory method / constructorthis.Position.prototype.instance =function(params){returnnewthis.constructor().setLatitude(params.latitude).setLongitude(params.longitude);};returnnewthis.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
Используя в качестве ссылки эту страницу и документацию (которая, кажется, значительно улучшилась с тех пор, как я в последний раз смотрел), я собрал следующую (-ish) демонстрацию мира, в которой используются 4 из 5 вариантов провайдера; Значение, Постоянный, Заводской и полномасштабный Провайдер.
HTML:
<divng-controller="mainCtrl as main"><h1>{{main.title}}*</h1><h2>{{main.strapline}}</h2><p>Earn {{main.earn}} per click</p><p>You've earned {{main.earned}} by clicking!</p><buttonng-click="main.handleClick()">Click me to earn</button><small>* Not actual money</small></div>
приложение
var app = angular.module('angularProviders',[]);// A CONSTANT is not going to change
app.constant('range',100);// A VALUE could change, but probably / typically doesn't
app.value('title','Earn money by clicking');
app.value('strapline','Adventures in ng Providers');// A simple FACTORY allows us to compute a value @ runtime.// Furthermore, it can have other dependencies injected into it such// as our range constant.
app.factory('random',function randomFactory(range){// Get a random number within the range defined in our CONSTANTreturnMath.random()* range;});// A PROVIDER, must return a custom type which implements the functionality // provided by our service (see what I did there?).// Here we define the constructor for the custom type the PROVIDER below will // instantiate and return.varMoney=function(locale){// Depending on locale string set during config phase, we'll// use different symbols and positioning for any values we // need to display as currencythis.settings ={
uk:{
front:true,
currency:'£',
thousand:',',decimal:'.'},
eu:{
front:false,
currency:'€',
thousand:'.',decimal:','}};this.locale = locale;};// Return a monetary value with currency symbol and placement, and decimal // and thousand delimiters according to the locale set in the config phase.Money.prototype.convertValue =function(value){var settings =this.settings[this.locale],
decimalIndex, converted;
converted =this.addThousandSeparator(value.toFixed(2), settings.thousand);
decimalIndex = converted.length -3;
converted = converted.substr(0, decimalIndex)+
settings.decimal+
converted.substr(decimalIndex +1);
converted = settings.front ?
settings.currency + converted :
converted + settings.currency;return converted;};// Add supplied thousand separator to supplied valueMoney.prototype.addThousandSeparator =function(value, symbol){returnvalue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, symbol);};// PROVIDER is the core recipe type - VALUE, CONSTANT, SERVICE & FACTORY// are all effectively syntactic sugar built on top of the PROVIDER construct// One of the advantages of the PROVIDER is that we can configure it before the// application starts (see config below).
app.provider('money',functionMoneyProvider(){var locale;// Function called by the config to set up the providerthis.setLocale =function(value){
locale =value;};// All providers need to implement a $get method which returns// an instance of the custom class which constitutes the servicethis.$get =function moneyFactory(){returnnewMoney(locale);};});// We can configure a PROVIDER on application initialisation.
app.config(['moneyProvider',function(moneyProvider){
moneyProvider.setLocale('uk');//moneyProvider.setLocale('eu'); }]);// The ubiquitous controller
app.controller('mainCtrl',function($scope, title, strapline, random, money){// Plain old VALUE(s)this.title = title;this.strapline = strapline;this.count =0;// Compute values using our money provider this.earn = money.convertValue(random);// random is computed @ runtimethis.earned = money.convertValue(0);this.handleClick =function(){this.count ++;this.earned = money.convertValue(random *this.count);};});
как Factory, Service и Constant - просто синтаксический сахар поверх рецепта поставщика?
ИЛИ
как фабрика, сервис и провайдеры внутренне симилар
в основном то, что происходит
Когда вы сделаете factory()это наборами вы при functionусловии , во втором аргументе провайдера $getи вернуть его ( provider(name, {$get:factoryFn })), все , что вы получаете, providerно нет никакой собственности / метода, кроме$get того , чтоprovider (значит, вы не можете настроить это)
Когда service()вы возвращаете его, вы предоставляете factory () функцию, functionкоторая внедряет constructor(возвращает экземпляр конструктора, предоставленного вами в вашем сервисе) и возвращает его
Исходный код сервиса
function service(name,constructor){return factory(name,['$injector',function($injector){return $injector.instantiate(constructor);}]);};
Таким образом, в основном в обоих случаях вы в конечном итоге получаете $ провайдера, настроенного на вашу функцию, которую вы предоставили, но вы можете дать что-то большее, чем $ get, как вы могли изначально предоставить в provider () для блока конфигурации
Я знаю много отличных ответов, но я должен поделиться своим опытом использования
1. serviceдля большинства случаев по умолчанию
2. factoryиспользуется для создания службы для этого конкретного экземпляра
Немного опоздал на вечеринку. Но я подумал, что это более полезно для тех, кто хотел бы узнать (или иметь ясность) о разработке пользовательских служб Angular JS с использованием методологий фабрики, сервиса и провайдера.
Я наткнулся на это видео, в котором четко объясняются методологии фабрики, сервиса и провайдера для разработки пользовательских сервисов AngularJS:
Код, размещенный здесь, скопирован прямо из вышеуказанного источника, чтобы помочь читателям.
Код для настраиваемой службы, основанной на фабрике, выглядит следующим образом (который используется как для синхронизации, так и для асинхронной версии, а также для вызова службы http):
Наконец, пользовательский интерфейс, который работает с любым из вышеперечисленных сервисов:
<html><head><title></title><scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script><scripttype="text/javascript"src="t03.js"></script></head><bodyng-app="app"><divng-controller="emp"><div>
Value of a is {{a}},
but you can change
<inputtype=textng-model="a"/><br>
Value of b is {{b}},
but you can change
<inputtype=textng-model="b"/><br></div>
Sum = {{sum}}<br><buttonng-click="doSum()">Calculate</button></div></body></html>
Просто чтобы прояснить ситуацию, из источника AngularJS вы можете увидеть, что сервис просто вызывает фабричную функцию, которая, в свою очередь, вызывает функцию провайдера:
function factory(name, factoryFn){return provider(name,{ $get: factoryFn });}function service(name,constructor){return factory(name,['$injector',function($injector){return $injector.instantiate(constructor);}]);}
Давайте обсудим три способа простой обработки бизнес-логики в AngularJS: ( Вдохновленный курсом Яакова Coursera AngularJS )
СЕРВИС :
Синтаксис:
app.js
var app = angular.module('ServiceExample',[]);var serviceExampleController =
app.controller('ServiceExampleController',ServiceExampleController);var serviceExample = app.service('NameOfTheService',NameOfTheService);ServiceExampleController.$inject =['NameOfTheService']//protects from minification of js filesfunctionServiceExampleController(NameOfTheService){
serviceExampleController =this;
serviceExampleController.data =NameOfTheService.getSomeData();}functionNameOfTheService(){
nameOfTheService =this;
nameOfTheService.data ="Some Data";
nameOfTheService.getSomeData =function(){return nameOfTheService.data;}}
index.html
<divng-controller="ServiceExampleController as serviceExample">
{{serviceExample.data}}
</div>
Особенности сервиса:
Ленивый экземпляр : если он не введен, он никогда не будет создан. Таким образом, чтобы использовать его, придется ввести его в модуль.
Singleton : если внедрено в несколько модулей, все будут иметь доступ только к одному конкретному экземпляру. Именно поэтому очень удобно обмениваться данными между разными контроллерами.
ФАБРИКА
Сначала давайте посмотрим на синтаксис:
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 functionfunctionNameOfTheFactoryOne(){var factory =function(){returnnewSomeService();}return factory;}//second implementation where an object literal would be returnedfunctionNameOfTheFactoryTwo(){var factory ={
getSomeService :function(){returnnewSomeService();}};return factory;}
Теперь с помощью двух выше в контроллере:
var factoryOne =NameOfTheFactoryOne()//since it returns a function
factoryOne.someMethod();var factoryTwo =NameOfTheFactoryTwo.getSomeService();//accessing the object
factoryTwo.someMethod();
Особенности Фабрики:
Следует шаблону фабричного дизайна. Фабрика - это центральное место, которое производит новые объекты или функции.
Производит не только синглтон, но и настраиваемые сервисы.
.service()Метод является заводом , который всегда производит один и тот же тип сервиса, который одноэлементен, и без какого - либо простого способа настроить его поведение. Этот .service()метод обычно используется в качестве ярлыка для чего-то, что не требует какой-либо настройки.
Провайдер - самый гибкий способ создания сервисов в Angular.
Мы не только можем создать фабрику, которая динамически настраивается, но во время использования фабрики с помощью метода провайдера мы могли настраивать фабрику только один раз при начальной загрузке всего нашего приложения.
Завод может быть использован во всем приложении с пользовательскими настройками. Другими словами, мы можем настроить эту фабрику до запуска приложения. На самом деле в угловой документации упоминаются , что метод провайдера , что на самом деле получает выполняется за кулисами , когда мы настраиваем наши услуги либо .serviceили .factoryметоды.
Это $getфункция, которая напрямую связана с экземпляром провайдера. Эта функция является заводской функцией. Другими словами, это так же , как тот , который мы используем , чтобы обеспечить к .factoryметоду. В этой функции мы создаем наш собственный сервис. Это $getсвойство, то есть функция, делает провайдера провайдером . AngularJS ожидает, что у провайдера будет свойство $ get, значением которого является функция, которую Angular будет рассматривать как фабричную функцию. Но что делает всю эту настройку поставщика очень особенной, так это то, что мы можем предоставить некоторый configобъект внутри поставщика услуг, и это обычно идет со значениями по умолчанию, которые мы можем позже перезаписать на шаге, где мы можем настроить все приложение.
Фабрика: фабрика, на которой вы фактически создаете объект внутри фабрики и возвращаете его. сервис: сервис, у вас просто есть стандартная функция, которая использует ключевое слово this для определения функции. провайдер: в качестве провайдера вы определяете $ get, и его можно использовать для получения объекта, который возвращает данные.
По сути, Поставщик, Завод и Сервис - все это Услуги. Фабрика - это особый случай службы, когда все, что вам нужно, это функция $ get (), позволяющая писать ее с меньшим количеством кода.
Основными различиями между Сервисами, Фабриками и Поставщиками являются их сложности. Службы являются самой простой формой, фабрики немного более устойчивы, а провайдеры настраиваются во время выполнения.
Вот краткое изложение того, когда использовать каждый:
Фабрика : предоставляемое вами значение должно быть рассчитано на основе других данных.
Сервис : вы возвращаете объект с методами.
Поставщик : вы хотите иметь возможность настроить на этапе настройки объект, который будет создан до его создания. Используйте поставщика в основном в конфигурации приложения, прежде чем приложение будет полностью инициализировано.
эм. Value, Factory, Service и Constant - это просто синтаксический сахар на вершине рецепта поставщика. Документы Angularjs - провайдеры
Sudarshan_SMD
да, я согласен, теперь с угловым 4 у нас больше нет этой головной боли
eGhoul
4
1.Услуги - это одноэлементные объекты, которые создаются при необходимости и никогда не очищаются до конца жизненного цикла приложения (когда браузер закрыт). Контроллеры уничтожаются и очищаются, когда они больше не нужны.
2. Самый простой способ создать сервис - использовать метод factory (). Метод factory () позволяет нам определять службу, возвращая объект, который содержит функции службы и данные службы. Функция определения сервиса - это место, где мы размещаем наши инъекционные сервисы, такие как $ http и $ q. Пример:
Метод service (), с другой стороны, позволяет нам создавать сервис, определяя функцию конструктора. Мы можем использовать прототипный объект для определения нашего сервиса вместо необработанного объекта JavaScript. Подобно методу factory (), мы также установим инъецируемые элементы в определении функции.
Самым низким способом создания сервиса является использование метода provide (). Это единственный способ создать службу, которую мы можем настроить с помощью функции .config (). В отличие от предыдущих методов, мы будем устанавливать инъецируемые объекты в определенном определении функции. $ Get ().
Синтаксический сахар - это разница . Нужен только провайдер. Или, другими словами, реальным углом является только поставщик, все остальные являются производными (для уменьшения кода). Существует также простая версия, называемая Value (), которая возвращает только значение, без вычисления или функции. Четное значение получено от поставщика!
Так почему такие сложности, почему мы не можем просто использовать провайдера и забыть обо всем остальном? Предполагается, что это поможет нам легче писать код и лучше общаться. И ответ будет сложнее, чем сложнее он становится, тем лучше будет продажа фреймворка.
Поставщик, который может вернуть значение = Значение
Поставщик, который может просто создать экземпляр и вернуть = Factory (+ Value)
Поставщик, который может создать экземпляр + сделать что-то = Служба (+ Фабрика, + Значение)
Поставщик = должен содержать свойство с именем $ get (+ Factory, + Service, + Value)
Угловая инъекция дает нам первый намек в достижении этого заключения.
«$ injector используется для извлечения экземпляров объекта, как определено поставщиком », не службой, не фабрикой, а провайдером.
И лучшим ответом было бы следующее: «Служба Angular создается фабрикой сервисов. Эти фабрики сервисов являются функциями, которые, в свою очередь, создаются поставщиком услуг. Поставщики услуг являются функциями конструктора. При реализации они должны содержать свойство называется $ get, который содержит функцию фабрики сервиса. "
Так что мастер провайдер и инжектор и все встанет на свои места :). И в Typescript становится интересным, когда $ get может быть реализован в провайдере путем наследования от IServiceProvider.
service.factory
. Не хотел усложнять эту тему дальше.services
,какfactories
и какproviders
работает.Ответы:
Из списка рассылки AngularJS я получил удивительную ветку, в которой объясняются сервисы против фабрики, против провайдеров и их использование. Составление ответов:
Сервисы
Синтаксис:
module.service( 'serviceName', function );
Результат: при объявлении serviceName в качестве вводимого аргумента вам будет предоставлен экземпляр функции. Другими словами
new FunctionYouPassedToService()
.Заводы
Синтаксис:
module.factory( 'factoryName', function );
Результат: при объявлении factoryName в качестве вводимого аргумента вам будет предоставлено значение, возвращаемое путем вызова ссылки на функцию, переданной в module.factory .
Провайдеры
Синтаксис:
module.provider( 'providerName', function );
Результат: При объявлении providerName в качестве вводимого аргумента вам будет предоставлено
(new ProviderFunction()).$get()
. Функция конструктораProviderFunction
создается перед вызовом метода $ get - это ссылка на функцию, переданную в module.provider.Преимущество провайдеров заключается в том, что их можно настраивать на этапе настройки модуля.
Смотрите здесь для предоставленного кода.
Вот большое дальнейшее объяснение Миско:
В этом случае инжектор просто возвращает значение как есть. Но что, если вы хотите вычислить значение? Тогда используйте фабрику
Такова
factory
функция, которая отвечает за создание стоимости. Обратите внимание, что фабричная функция может запрашивать другие зависимости.Но что, если вы хотите быть более интересным и иметь класс под названием Greeter?
Тогда для создания экземпляра вам придется написать
Тогда мы могли бы попросить «приветствовать» в контроллере, как это
Но это слишком многословно. Более короткий способ написать это будет
provider.service('greeter', Greeter);
Но что, если мы хотим настроить
Greeter
класс до внедрения? Тогда мы могли бы написатьТогда мы можем сделать это:
В качестве примечания,
service
,factory
, иvalue
все получены от поставщика.источник
toEqual
иgreeter.Greet
есть. Почему бы не использовать что-то более реальное и подходящее?JS Fiddle Demo
Пример "Hello world" с
factory
/service
/provider
:источник
this
меняет контекст в$get
функции? - вы больше не обращаетесь к конкретному провайдеру в этой функции.this
фактически не меняет контекст, потому что то, что вызывается, этоnew Provider()
. $ Get (), гдеProvider
передается функцияapp.provider
. Это значит, что он$get()
вызывается как метод на построенном объектеProvider
, поэтому мыthis
будем ссылаться на него,Provider
как показывает пример.Unknown provider: helloWorldProvider <- helloWorld
при запуске этого локально? Комментируя это, та же ошибка для двух других примеров. Есть ли какая-то скрытая конфигурация провайдера? (Angular 1.0.8) - Найдено: stackoverflow.com/questions/12339272/…TL; DR
1) Когда вы используете Factory, вы создаете объект, добавляете к нему свойства, а затем возвращаете тот же объект. Когда вы передадите эту фабрику в свой контроллер, эти свойства объекта теперь будут доступны в этом контроллере через вашу фабрику.
2) Когда вы используете Сервис , AngularJS создает его за кулисами с ключевым словом «new». Из-за этого вы добавите свойства в «this», и сервис вернет «this». Когда вы передаете услугу в свой контроллер, эти свойства в «this» теперь будут доступны на этом контроллере через ваш сервис.
3) Поставщики - это единственная услуга, которую вы можете передать в функцию .config (). Используйте провайдера, если вы хотите предоставить конфигурацию всего модуля для объекта службы, прежде чем сделать его доступным.
Не TL; DR
1)
Фабрики - это самый популярный способ создания и настройки сервиса. Там действительно не намного больше, чем то, что сказал TL; DR. Вы просто создаете объект, добавляете к нему свойства, а затем возвращаете тот же объект. Затем, когда вы передадите фабрику в свой контроллер, эти свойства объекта теперь будут доступны в этом контроллере через вашу фабрику. Более подробный пример приведен ниже.
Теперь любые свойства, которые мы прикрепляем к «сервису», будут нам доступны, когда мы передадим «myFactory» в наш контроллер.
Теперь давайте добавим некоторые «приватные» переменные в нашу функцию обратного вызова. Они не будут напрямую доступны из контроллера, но мы в конечном итоге настроим некоторые методы получения / установки для «службы», чтобы иметь возможность изменять эти «частные» переменные при необходимости.
Здесь вы заметите, что мы не привязываем эти переменные / функцию к 'service'. Мы просто создаем их, чтобы потом использовать или модифицировать их.
Теперь, когда наши вспомогательные / закрытые переменные и функции на месте, давайте добавим некоторые свойства к объекту 'service'. Все, что мы ставим на «сервис», можно напрямую использовать внутри любого контроллера, в который мы передаем «myFactory».
Мы собираемся создать методы setArtist и getArtist, которые просто возвращают или устанавливают художника. Мы также собираемся создать метод, который будет вызывать iTunes API с нашим созданным URL. Этот метод возвращает обещание, которое будет выполнено, как только данные вернутся из iTunes API. Если у вас не было большого опыта использования обещаний в AngularJS, я настоятельно рекомендую глубоко погрузиться в них.
Ниже setArtist принимает художника и позволяет установить художника. getArtist возвращает художника. callItunes сначала вызывает makeUrl (), чтобы создать URL, который мы будем использовать с нашим запросом $ http. Затем он устанавливает объект обещания, делает запрос $ http с нашим окончательным URL, а затем, так как $ http возвращает обещание, мы можем вызвать .success или .error после нашего запроса. Затем мы выполняем наше обещание с помощью данных iTunes или отклоняем его с сообщением «Произошла ошибка».
Теперь наша фабрика завершена. Теперь мы можем внедрить 'myFactory' в любой контроллер, и тогда мы сможем вызывать наши методы, которые мы прикрепили к нашему сервисному объекту (setArtist, getArtist и callItunes).
В контроллере выше мы вводим в сервис «myFactory». Затем мы устанавливаем свойства нашего объекта $ scope с данными из myFactory. Единственный сложный код выше, если вы никогда не имели дело с обещаниями раньше. Поскольку callItunes возвращает обещание, мы можем использовать метод .then () и устанавливать $ scope.data.artistData только после того, как наше обещание будет выполнено с данными iTunes. Вы заметите, что наш контроллер очень «тонкий» (это хорошая практика кодирования). Вся наша логика и постоянные данные находятся в нашем сервисе, а не в нашем контроллере.
2) Сервис
Возможно, самая важная вещь, которую нужно знать при создании Сервиса, это то, что он создается с ключевым словом «new». Для вас, гуру JavaScript, это должно дать вам подсказку о природе кода. Для тех из вас, кто имеет ограниченный опыт работы с JavaScript, или тех, кто не слишком знаком с тем, что на самом деле делает ключевое слово «new», давайте рассмотрим некоторые основы JavaScript, которые в конечном итоге помогут нам понять природу Сервиса.
Чтобы действительно увидеть изменения, которые происходят при вызове функции с ключевым словом «new», давайте создадим функцию и вызовем ее с ключевым словом «new», а затем покажем, что делает интерпретатор, когда видит ключевое слово «new». Конечные результаты будут одинаковыми.
Сначала давайте создадим наш конструктор.
Это типичная функция конструктора JavaScript. Теперь всякий раз, когда мы вызываем функцию Person с помощью ключевого слова new, this будет привязано к вновь созданному объекту.
Теперь давайте добавим метод в прототип нашего Person, чтобы он был доступен для каждого экземпляра нашего класса Person.
Теперь, поскольку мы поместили функцию sayName в прототип, каждый экземпляр Person сможет вызывать функцию sayName в порядке оповещения об имени этого экземпляра.
Теперь, когда у нас есть функция конструктора Person и наша функция sayName в ее прототипе, давайте создадим экземпляр Person, а затем вызовем функцию sayName.
Таким образом, весь код для создания конструктора Person, добавления функции к его прототипу, создания экземпляра Person и последующего вызова функции для его прототипа выглядит следующим образом.
Теперь давайте посмотрим, что на самом деле происходит, когда вы используете ключевое слово «new» в JavaScript. Первое, что вы должны заметить, это то, что после использования «new» в нашем примере мы можем вызвать метод (sayName) для «tyler» так же, как если бы это был объект - так оно и есть. Итак, во-первых, мы знаем, что наш конструктор Person возвращает объект, видим ли мы это в коде или нет. Во-вторых, мы знаем, что поскольку наша функция sayName расположена в прототипе, а не непосредственно в экземпляре Person, объект, который возвращает функция Person, должен делегировать своему прототипу при неудачных поисках. Проще говоря, когда мы вызываем tyler.sayName (), интерпретатор говорит: «Хорошо, я собираюсь посмотреть на только что созданный объект« tyler », найти функцию sayName, а затем вызвать ее. Подожди, я не вижу этого здесь - все, что я вижу, это имя и возраст, позвольте мне проверить прототип. Да, похоже, что это на прототипе, позвольте мне назвать это ».
Ниже приведен код того, как вы можете думать о том, что на самом деле делает ключевое слово «новый» в JavaScript. Это в основном пример кода вышеупомянутого абзаца. Я поместил «представление интерпретатора» или то, как интерпретатор видит код внутри заметок.
Теперь, имея представление о том, что на самом деле делает ключевое слово «новое» в JavaScript, создание службы в AngularJS должно быть проще для понимания.
Самая важная вещь, которую нужно понять при создании Сервиса, это знание того, что Сервисы создаются с помощью ключевого слова «new». Объединяя эти знания с нашими примерами выше, вы теперь должны понимать, что вы будете привязывать свои свойства и методы непосредственно к «this», которое затем будет возвращено из самой Службы. Давайте посмотрим на это в действии.
В отличие от того, что мы изначально делали с примером Factory, нам не нужно создавать объект, а затем возвращать этот объект, потому что, как упоминалось много раз ранее, мы использовали ключевое слово «new», поэтому интерпретатор создаст этот объект, предоставив ему делегирование это прототип, а затем верните его нам без необходимости выполнять работу.
Прежде всего, давайте создадим нашу «приватную» и вспомогательную функцию. Это должно выглядеть очень знакомо, так как мы сделали то же самое с нашим заводом. Я не буду объяснять, что здесь делает каждая строка, потому что я сделал это в заводском примере, если вы не уверены, перечитайте заводской пример.
Теперь мы прикрепим все наши методы, которые будут доступны в нашем контроллере, к «this».
Теперь, как и на нашей фабрике, setArtist, getArtist и callItunes будут доступны в любом контроллере, в который мы передаем myService. Вот контроллер myService (который почти такой же, как наш заводской контроллер).
Как я уже упоминал ранее, когда вы действительно понимаете, что делает «новое», Сервисы практически идентичны фабрикам в AngularJS.
3) Провайдер
Самое важное, что нужно помнить о провайдерах, это то, что они являются единственной службой, которую вы можете передать в часть app.config вашего приложения. Это имеет огромное значение, если вам нужно изменить какую-то часть вашего сервисного объекта, прежде чем он станет доступен везде в вашем приложении. Хотя это очень похоже на Услуги / Фабрики, есть несколько различий, которые мы обсудим.
Сначала мы настраиваем нашего провайдера аналогично тому, как мы работали с нашим сервисом и фабрикой. Переменные ниже являются нашей «приватной» и вспомогательной функцией.
* Опять же, если какая-либо часть приведенного выше кода вводит в заблуждение, ознакомьтесь с разделом «Фабрика», где я объясняю, для чего все это более подробно.
Вы можете думать о провайдерах как о трех разделах. Первый раздел - это «частные» переменные / функции, которые будут изменены / установлены позже (показано выше). Второй раздел - это переменные / функции, которые будут доступны в вашей функции app.config и, следовательно, доступны для изменения до того, как они станут доступны где-либо еще (также показано выше). Важно отметить, что эти переменные должны быть присоединены к ключевому слову this. В нашем примере, только 'thingFromConfig' будет доступен для изменения в app.config. Третий раздел (показанный ниже) - это все переменные / функции, которые будут доступны в вашем контроллере, когда вы передадите службу myProvider в этот конкретный контроллер.
При создании службы с помощью Provider в вашем контроллере будут доступны только те свойства / методы, которые возвращаются из функции $ get (). Приведенный ниже код помещает $ get в this (которое, как мы знаем, будет возвращено из этой функции). Теперь эта функция $ get возвращает все методы / свойства, которые мы хотим быть доступными в контроллере. Вот пример кода.
Теперь полный код провайдера выглядит следующим образом
Теперь, как и на нашей фабрике, Service, setArtist, getArtist и callItunes будут доступны в любом контроллере, в который мы передаем myProvider. Вот контроллер myProvider (который почти такой же, как наш заводской / сервисный контроллер).
Как упоминалось ранее, весь смысл создания службы с помощью Provider заключается в возможности изменять некоторые переменные с помощью функции app.config до того, как конечный объект будет передан остальной части приложения. Давайте посмотрим пример этого.
Теперь вы можете видеть, как 'thingFromConfig' является пустой строкой в нашем провайдере, но когда это появится в DOM, это будет "Это предложение было установлено ...".
источник
Все Сервисы являются одиночными ; они создаются один раз за приложение. Они могут быть любого типа , будь то примитив, литерал объекта, функция или даже экземпляр пользовательского типа.
value
,factory
,service
,constant
, Иprovider
методы все провайдеры. Они учат Инжектора, как создавать Услуги.decorator
.источник
Понимание AngularJS Factory, Сервис и Поставщик
Все они используются для совместного использования одноразовых объектов. Это помогает обмениваться повторно используемым кодом через ваше приложение / различные компоненты / модули.
завод
Фабрика - это функция, в которой вы можете манипулировать / добавлять логику перед созданием объекта, после чего возвращается вновь созданный объект.
Применение
Это может быть просто набор функций, таких как класс. Следовательно, он может быть создан в разных контроллерах, когда вы вводите его в функции контроллера / фабрики / директивы. Он создается только один раз за приложение.
обслуживание
Просто, глядя на сервисы, подумайте о прототипе массива. Служба - это функция, которая создает новый объект, используя ключевое слово «new». Вы можете добавить свойства и функции к объекту службы, используя
this
ключевое слово. В отличие от фабрики, он ничего не возвращает (он возвращает объект, который содержит методы / свойства).Применение
Используйте его, когда вам нужно поделиться одним объектом по всему приложению. Например, данные пользователя, прошедшего проверку подлинности, методы / данные для совместного использования, функции служебных программ и т. Д.
поставщик
Поставщик используется для создания настраиваемого объекта службы. Вы можете настроить параметры сервиса из функции конфигурации. Возвращает значение с помощью
$get()
функции.$get
Функция запускается на выполнение на этапе выполнения в угловой.Применение
Когда вам нужно предоставить модульную конфигурацию для вашего сервисного объекта, прежде чем сделать его доступным, например. Предположим, вы хотите установить URL-адрес API на основе вашей среды, например
dev
,stage
илиprod
Надеюсь, что это прояснило ваше понимание о фабрике, обслуживании и поставщике .
источник
only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications
, так что не кажется возможным, верно?Для меня откровение пришло, когда я понял, что все они работают одинаково: запустив что-то один раз , сохранив полученное значение, а затем обработайте то же самое сохраненное значение, когда на него ссылаются посредством внедрения зависимостей .
Скажем, у нас есть:
Разница между тремя заключается в том, что:
a
сохраненное значение приходит от запускаfn
.b
сохраненное значение исходит отnew
ingfn
.c
Хранимое значение приходит от первого получения экземпляра с помощьюnew
ingfn
, а затем запуска$get
метода экземпляра.Это означает, что внутри AngularJS есть что-то вроде объекта кеша, значение которого для каждой инъекции присваивается только один раз, когда они были введены впервые, и где:
Вот почему мы используем
this
в сервисах, а определяемthis.$get
в провайдерах.источник
factory
с. Единственная причинаservice
существования - это языки, такие как CoffeeScript, TypeScript, ES6 и т. Д., Поэтому вы можете использовать синтаксис их классов. Вам нужныprovider
s, только если ваш модуль используется в нескольких приложениях с разными настройками при помощиapp.config()
. Если ваш сервис является чисто одноэлементным или способен создавать экземпляры чего-либо, зависит только от вашей реализации.Сервис против провайдера против фабрики:
Я пытаюсь сделать это простым. Это все о базовой концепции JavaScript.
Прежде всего, давайте поговорим об услугах в AngularJS!
Что такое Сервис: В AngularJS, Сервисэто не что иное, как одиночный объект JavaScript, который может хранить некоторые полезные методы или свойства. Этот одноэлементный объект создается на основе ngApp (приложение Angular) и используется всеми контроллерами в текущем приложении. Когда Angularjs создает объект службы, он регистрирует этот объект службы с уникальным именем службы. Поэтому каждый раз, когда нам нужен экземпляр службы, Angular ищет в реестре это имя службы и возвращает ссылку на объект службы. Таким образом, мы можем вызвать метод, получить доступ к свойствам и т. Д. На объекте службы. У вас может возникнуть вопрос, можете ли вы также поместить свойства, методы в объектную область контроллеров! Так зачем вам сервисный объект? Ответы таковы: сервисы распределяются между несколькими контроллерами. Если вы поместите некоторые свойства / методы в объект области видимости контроллера, он будет доступен только для текущей области видимости.
Таким образом, если существует три области контроллера, пусть это будут controllerA, controllerB и controllerC, все они будут использовать один и тот же экземпляр службы.
Как создать сервис?
AngularJS предоставляет различные методы для регистрации службы. Здесь мы сосредоточимся на трех методах: фабрика (..), сервис (..), провайдер (..);
Используйте эту ссылку для ссылки на код
Заводская функция:
Мы можем определить фабричную функцию, как показано ниже.
AngularJS предоставляет метод factory ('serviceName', fnFactory) ', который принимает два параметра, serviceName и функцию JavaScript. Angular создает экземпляр службы, вызывая функцию fnFactory (), например ниже.
Переданная функция может определить объект и вернуть этот объект. AngularJS просто сохраняет эту ссылку на объект в переменную, которая передается в качестве первого аргумента. Все, что возвращается из fnFactory, будет связано с serviceInstance. Вместо того, чтобы возвращать объект, мы также можем возвращать функцию, значения и т. Д. Что бы мы ни возвращали, они будут доступны экземпляру службы.
Пример:
Сервисная функция:
Это еще один способ, мы можем зарегистрировать услугу. Единственное отличие состоит в том, как AngularJS пытается создать экземпляр объекта службы. На этот раз angular использует ключевое слово «new» и вызывает функцию конструктора, как показано ниже.
В функции конструктора мы можем использовать ключевое слово this для добавления свойств / методов к объекту службы. пример:
Функция провайдера:
Функция Provider () - это еще один способ создания сервисов. Пусть нам интересно создать сервис, который просто отображает какое-то приветственное сообщение пользователю. Но мы также хотим предоставить такую функциональность, чтобы пользователь мог установить собственное приветственное сообщение. В техническом плане мы хотим создавать настраиваемые сервисы. Как мы можем это сделать ? Должен быть способ, чтобы приложение могло передавать свои пользовательские приветственные сообщения, а Angularjs делал бы его доступным для функции фабрики / конструктора, которая создает наш экземпляр сервисов. В таком случае функция provider () выполняет свою работу. используя функцию provider (), мы можем создавать настраиваемые сервисы.
Мы можем создавать настраиваемые сервисы, используя синтаксис провайдера, как указано ниже.
Как работает синтаксис провайдера?
1.Provider объект создается с помощью функции конструктора, которую мы определили в нашей функции провайдера.
2. Функция, которую мы передали в app.config (), выполняется. Это называется этапом конфигурации, и здесь у нас есть возможность настроить наш сервис.
3. Наконец, экземпляр службы создается путем вызова $ get метода serviceProvider.
Пример кода для создания сервиса с использованием синтаксиса:
Рабочая Демо
Резюме:
Фабрика использует фабричную функцию, которая возвращает экземпляр службы. serviceInstance = fnFactory ();
Сервис использует функцию конструктора, и Angular вызывает эту функцию конструктора, используя ключевое слово «new» для создания экземпляра сервиса. serviceInstance = new fnServiceConstructor ();
Provider определяет функцию providerConstructor, эта функция providerConstructor определяет фабричную функцию $ get . Angular вызывает $ get () для создания объекта службы. Синтаксис провайдера имеет дополнительное преимущество в настройке объекта службы перед его созданием. serviceInstance = $ get ();
источник
Как правильно отметили несколько человек, фабрика, поставщик, сервис и даже значение и константа являются версиями одного и того же. Вы можете разбить более общее
provider
на всех из них. Вот так:Вот статья, из которой это изображение:
http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/
источник
завод
Вы даете AngularJS функцию, AngularJS будет кешировать и вводить возвращаемое значение, когда запрашивается фабрика.
Пример:
Применение:
обслуживание
Вы даете AngularJS функцию, AngularJS вызовет new, чтобы создать ее экземпляр. Это экземпляр, который создает AngularJS, который будет кэшироваться и вставляться при запросе сервиса. Поскольку new использовался для создания экземпляра службы, ключевое слово this является действительным и относится к экземпляру.
Пример:
Применение:
поставщик
Вы даете AngularJS функцию, а AngularJS будет вызывать ее
$get
функцию. Это возвращаемое значение из$get
функции, которая будет кэшироваться и вставляться при запросе службы.Провайдеры позволяют вам настроить провайдера до того, как AngularJS
$get
вызовет метод, чтобы получить инъекцию.Пример:
Использование (как инъекция в контроллере)
Использование (настройка провайдера перед
$get
вызовом для создания инъекционного)источник
Я заметил кое-что интересное, играя с провайдерами.
Видимость инъекционных препаратов различна для поставщиков, чем для служб и предприятий. Если вы объявите AngularJS «константой» (например,
myApp.constant('a', 'Robert');
), вы можете внедрить его в службы, фабрики и поставщиков.Но если вы объявите AngularJS «значение» (например,.
myApp.value('b', {name: 'Jones'});
), Вы можете внедрить его в службы и фабрики, но НЕ в функцию создания провайдера. Однако вы можете добавить его в$get
функцию, определенную для вашего провайдера. Это упоминается в документации AngularJS, но это легко пропустить. Вы можете найти его на странице% provide в разделах о методах value и constant.http://jsfiddle.net/R2Frv/1/
источник
Это очень запутанная часть для новичка, и я попытался объяснить это простыми словами
Служба AngularJS: используется для совместного использования служебных функций со ссылкой на службу в контроллере. Служба является одноэлементной по своей природе, поэтому для одного сервиса в браузере создается только один экземпляр, и одна и та же ссылка используется на всей странице.
В сервисе мы создаем имена функций как свойства этого объекта.
AngularJS Factory: назначение Factory также совпадает с Service, однако в этом случае мы создаем новый объект и добавляем функции в качестве свойств этого объекта, а в конце возвращаем этот объект.
Поставщик AngularJS: цель этого снова та же, однако поставщик предоставляет вывод своей функции $ get.
Определение и использование Сервиса, Фабрики и Поставщика объясняются по адресу http://www.dotnetfunda.com/articles/show/3156/difference-between-angularjs-service-factory-and-provider.
источник
Для меня лучший и самый простой способ понять разницу это:
Как AngularJS создает конкретные компоненты (упрощенно):
Таким образом, для службы то, что становится компонентом AngularJS, является экземпляром объекта класса, который представлен функцией объявления службы. Для фабрики это результат, возвращаемый функцией объявления фабрики. Фабрика может вести себя так же, как сервис:
Самый простой способ мышления следующий:
Пример фабричного «класса» приведен в комментариях, а также о разнице поставщиков.
источник
new MyService()
или что-то :)Мои разъяснения по этому вопросу:
В основном все упомянутые типы (сервис, фабрика, поставщик и т. Д.) Просто создают и настраивают глобальные переменные (которые, конечно, являются глобальными для всего приложения), как это делали устаревшие глобальные переменные.
Хотя глобальные переменные не рекомендуются, реальное использование этих глобальных переменных заключается в обеспечении внедрения зависимостей путем передачи переменной соответствующему контроллеру.
Существует много уровней сложности при создании значений для «глобальных переменных»:
Это определяет фактическую константу, которая не должна изменяться в течение всего приложения, так же как и константы в других языках (чего нет в JavaScript).
Это изменяемое значение или объект, и он служит некоторой глобальной переменной, которую можно даже внедрить при создании других служб или фабрик (см. Далее). Тем не менее, это должно быть « буквальное значение », что означает, что нужно выписать фактическое значение и не может использовать какую-либо логику вычислений или программирования (другими словами, 39 или myText или {prop: «value»} в порядке, но 2 +2 нет).
Более общее значение, которое можно вычислить сразу. Он работает путем передачи функции в AngularJS с логикой, необходимой для вычисления значения, и AngularJS выполняет ее, и сохраняет возвращаемое значение в именованной переменной.
Обратите внимание, что можно вернуть объект (в этом случае он будет функционировать аналогично службе ) или функцию (которая будет сохранена в переменной как функция обратного вызова).
Служба - это более урезанная версия фабрики, которая действует только тогда, когда значение является объектом, и она позволяет писать любую логику непосредственно в функции (как если бы она была конструктором), а также объявлять и получать доступ свойства объекта с использованием этого ключевого слова.
В отличие от сервиса, который является упрощенной версией фабрики , провайдер является более сложным, но более гибким способом инициализации «глобальных» переменных, при этом наибольшей гибкостью является возможность установки значений из app.config.
Это работает как использование комбинации службы и поставщика , передавая поставщику функцию, свойства которой объявлены с использованием ключевого слова this , которое можно использовать из
app.config
.Затем он должен иметь отдельную функцию $ .get, которая выполняется AngularJS после установки указанных выше свойств через
app.config
файл, и эта функция $ .get ведет себя так же, как фабрика выше, тем, что его возвращаемое значение используется для инициализации «глобальных» переменных.источник
Мое понимание очень просто ниже.
Фабрика: вы просто создаете объект внутри фабрики и возвращаете его.
Обслуживание:
У вас просто есть стандартная функция, которая использует это ключевое слово для определения функции.
Поставщик:
Существует
$get
объект, который вы определяете, и его можно использовать для получения объекта, который возвращает данные.источник
Резюме из угловых документов :
Лучшие ответы от SO:
https://stackoverflow.com/a/26924234/165673 (<- ХОРОШО) https://stackoverflow.com/a/27263882/165673
https://stackoverflow.com/a/16566144/165673
источник
Все хорошие ответы уже. Я хотел бы добавить еще несколько пунктов на Сервис и Фабрика . Вместе с разницей между сервисом / фабрикой. И можно также иметь такие вопросы, как:
Давайте начнем с разницы между обслуживанием и фабрикой:
Оба являются синглетонами : всякий раз, когда Angular находит их как зависимость в первый раз, он создает один экземпляр сервиса / фабрики. Как только экземпляр создан, тот же экземпляр используется навсегда.
Может использоваться для моделирования объекта с поведением : у них могут быть методы, внутренние переменные состояния и т. Д. Хотя способ написания этого кода будет отличаться.
Сервисы:
Сервис - это функция конструктора, и Angular создаст его экземпляр, вызвав new
yourServiceName()
. Это означает пару вещей.this
.new yourServiceName(
), он получитthis
объект со всеми свойствами, которые вы на него наделили.Пример примера:
Будьте осторожны с
this
:Поскольку созданный сервис является объектом, методы внутри него могут ссылаться на него при вызове:
У вас может возникнуть соблазн вызвать
ScoreKeeper.setScore
цепочку обещаний, например, если вы инициализировали счет, взяв его с сервера:$http.get('/score').then(ScoreKeeper.setScore).
проблема в том, чтоScoreKeeper.setScore
он будет вызван сthis
привязкой к,null
и вы получите ошибки. Лучший способ был бы$http.get('/score').then(ScoreKeeper.setScore.bind(ScoreKeeper))
. Если вы решите использовать это в своих методах обслуживания или нет, будьте осторожны, как вы их называете.Возврат значения из
Service
:Из-за того, как работают конструкторы JavaScript, если вы возвращаете комплексное значение
(i.e., an Object)
изconstructor
функции, вызывающая сторона получит этот объект вместо этого экземпляра.Это означает, что вы можете скопировать и вставить заводской пример снизу, заменить
factory
наservice
, и он будет работать:Поэтому, когда Angular создает ваш сервис с новым MyService (), он получает этот объект API вместо экземпляра MyService.
Это поведение для любых сложных значений (объектов, функций), но не для примитивных типов.
Заводы:
Фабрика - это простая старая функция, которая возвращает значение. Возвращаемое значение - это то, что вводится в вещи, которые зависят от фабрики. Типичный шаблон фабрики в Angular - возвращать объект с функциями в качестве свойств, например так:
Ответы на вопросы 1 и 2 выше:
источник
Дополнительным разъяснением является то, что фабрики могут создавать функции / примитивы, а службы - нет. Проверьте это jsFiddle на основе Epokk's: http://jsfiddle.net/skeller88/PxdSP/1351/ .
Фабрика возвращает функцию, которая может быть вызвана:
Фабрика также может вернуть объект с методом, который может быть вызван:
Служба возвращает объект с методом, который может быть вызван:
Для получения дополнительной информации см. Сообщение, которое я написал о разнице: http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/
источник
Уже есть хорошие ответы, но я просто хочу поделиться этим.
Прежде всего: Provider - это способ / рецепт для создания
service
(одноэлементного объекта), который должен быть введен $ инжектором (как AngulaJS использует шаблон IoC).И Value, Factory, Service и Constant (4 способа) - синтаксический сахар по сравнению с Provider way / recepie.
Там есть
Service vs Factory
часть была покрыта: https://www.youtube.com/watch?v=BLzNCkPn3aoСервис - это все о
new
ключевом слове, которое, как мы знаем, делает 4 вещи:prototype
объектомcontext
кthis
this
А Factory - это все о Factory Pattern - содержит функции, которые возвращают объекты, подобные этой службе.
И это простое / короткое видео: охватывает также провайдера : https://www.youtube.com/watch?v=HvTZbQ_hUZY (там, на котором вы видите, видно, как они идут от фабрики к провайдеру)
Рецепт провайдера используется в основном в конфигурации приложения до того, как приложение полностью запустится / инициализируется.
источник
После прочтения всех этих постов это создало больше путаницы для меня .. Но все же все это является полезной информацией .. наконец я нашел следующую таблицу, которая даст информацию с простым сравнением
И для начинающего понять: - Это может не исправить вариант использования, но на высоком уровне это то, что сценарий использования для этих трех.
Для базовых сценариев фабрика и сервис ведут себя одинаково.
источник
Вот пример кода, который я придумал как шаблон кода для фабрики объектов в AngularjS. Я использовал Car / CarFactory в качестве примера для иллюстрации. Делает для простой реализации кода в контроллере.
Вот более простой пример. Я использую несколько сторонних библиотек, которые ожидают объект «Положение», демонстрирующий широту и долготу, но через различные свойства объекта. Я не хотел взламывать код вендора, поэтому я настроил объекты «Положение», которые я передавал.
;
источник
Используя в качестве ссылки эту страницу и документацию (которая, кажется, значительно улучшилась с тех пор, как я в последний раз смотрел), я собрал следующую (-ish) демонстрацию мира, в которой используются 4 из 5 вариантов провайдера; Значение, Постоянный, Заводской и полномасштабный Провайдер.
HTML:
приложение
Рабочая демка .
источник
Этот ответ обратиться к теме / вопросу
как Factory, Service и Constant - просто синтаксический сахар поверх рецепта поставщика?
ИЛИ
как фабрика, сервис и провайдеры внутренне симилар
в основном то, что происходит
Когда вы сделаете
factory()
это наборами вы приfunction
условии , во втором аргументе провайдера$get
и вернуть его (provider(name, {$get:factoryFn })
), все , что вы получаете,provider
но нет никакой собственности / метода, кроме$get
того , чтоprovider
(значит, вы не можете настроить это)Исходный код фабрики
Когда
service()
вы возвращаете его, вы предоставляете factory () функцию,function
которая внедряетconstructor
(возвращает экземпляр конструктора, предоставленного вами в вашем сервисе) и возвращает егоИсходный код сервиса
Таким образом, в основном в обоих случаях вы в конечном итоге получаете $ провайдера, настроенного на вашу функцию, которую вы предоставили, но вы можете дать что-то большее, чем $ get, как вы могли изначально предоставить в provider () для блока конфигурации
источник
Я знаю много отличных ответов, но я должен поделиться своим опытом использования
1.
service
для большинства случаев по умолчанию2.
factory
используется для создания службы для этого конкретного экземпляраи используя:
источник
Немного опоздал на вечеринку. Но я подумал, что это более полезно для тех, кто хотел бы узнать (или иметь ясность) о разработке пользовательских служб Angular JS с использованием методологий фабрики, сервиса и провайдера.
Я наткнулся на это видео, в котором четко объясняются методологии фабрики, сервиса и провайдера для разработки пользовательских сервисов AngularJS:
https://www.youtube.com/watch?v=oUXku28ex-M
Исходный код: http://www.techcbt.com/Post/353/Angular-JS-basics/how-to-develop-angularjs-custom-service
Код, размещенный здесь, скопирован прямо из вышеуказанного источника, чтобы помочь читателям.
Код для настраиваемой службы, основанной на фабрике, выглядит следующим образом (который используется как для синхронизации, так и для асинхронной версии, а также для вызова службы http):
Код для «сервисной» методологии для пользовательских сервисов (это очень похоже на «фабрику», но отличается от синтаксической точки зрения):
Код для методологии «провайдера» для пользовательских сервисов (это необходимо, если вы хотите разработать сервис, который можно настроить):
Наконец, пользовательский интерфейс, который работает с любым из вышеперечисленных сервисов:
источник
Просто чтобы прояснить ситуацию, из источника AngularJS вы можете увидеть, что сервис просто вызывает фабричную функцию, которая, в свою очередь, вызывает функцию провайдера:
источник
Давайте обсудим три способа простой обработки бизнес-логики в AngularJS: ( Вдохновленный курсом Яакова Coursera AngularJS )
СЕРВИС :
Синтаксис:
app.js
index.html
Особенности сервиса:
ФАБРИКА
Сначала давайте посмотрим на синтаксис:
app.js :
Теперь с помощью двух выше в контроллере:
Особенности Фабрики:
.service()
Метод является заводом , который всегда производит один и тот же тип сервиса, который одноэлементен, и без какого - либо простого способа настроить его поведение. Этот.service()
метод обычно используется в качестве ярлыка для чего-то, что не требует какой-либо настройки.ПРОВАЙДЕР
Давайте снова посмотрим на синтаксис первым:
Особенности провайдера:
.service
или.factory
методы.$get
функция, которая напрямую связана с экземпляром провайдера. Эта функция является заводской функцией. Другими словами, это так же , как тот , который мы используем , чтобы обеспечить к.factory
методу. В этой функции мы создаем наш собственный сервис. Это$get
свойство, то есть функция, делает провайдера провайдером . AngularJS ожидает, что у провайдера будет свойство $ get, значением которого является функция, которую Angular будет рассматривать как фабричную функцию. Но что делает всю эту настройку поставщика очень особенной, так это то, что мы можем предоставить некоторыйconfig
объект внутри поставщика услуг, и это обычно идет со значениями по умолчанию, которые мы можем позже перезаписать на шаге, где мы можем настроить все приложение.источник
Фабрика: фабрика, на которой вы фактически создаете объект внутри фабрики и возвращаете его.
сервис: сервис, у вас просто есть стандартная функция, которая использует ключевое слово this для определения функции.
провайдер: в качестве провайдера вы определяете $ get, и его можно использовать для получения объекта, который возвращает данные.
источник
По сути, Поставщик, Завод и Сервис - все это Услуги. Фабрика - это особый случай службы, когда все, что вам нужно, это функция $ get (), позволяющая писать ее с меньшим количеством кода.
Основными различиями между Сервисами, Фабриками и Поставщиками являются их сложности. Службы являются самой простой формой, фабрики немного более устойчивы, а провайдеры настраиваются во время выполнения.
Вот краткое изложение того, когда использовать каждый:
Фабрика : предоставляемое вами значение должно быть рассчитано на основе других данных.
Сервис : вы возвращаете объект с методами.
Поставщик : вы хотите иметь возможность настроить на этапе настройки объект, который будет создан до его создания. Используйте поставщика в основном в конфигурации приложения, прежде чем приложение будет полностью инициализировано.
источник
1.Услуги - это одноэлементные объекты, которые создаются при необходимости и никогда не очищаются до конца жизненного цикла приложения (когда браузер закрыт). Контроллеры уничтожаются и очищаются, когда они больше не нужны.
2. Самый простой способ создать сервис - использовать метод factory (). Метод factory () позволяет нам определять службу, возвращая объект, который содержит функции службы и данные службы. Функция определения сервиса - это место, где мы размещаем наши инъекционные сервисы, такие как $ http и $ q. Пример:
Используя factory () в нашем приложении
В нашем приложении легко использовать фабрику, поскольку мы можем просто внедрить ее туда, где она нам нужна во время выполнения.
источник
Синтаксический сахар - это разница . Нужен только провайдер. Или, другими словами, реальным углом является только поставщик, все остальные являются производными (для уменьшения кода). Существует также простая версия, называемая Value (), которая возвращает только значение, без вычисления или функции. Четное значение получено от поставщика!
Так почему такие сложности, почему мы не можем просто использовать провайдера и забыть обо всем остальном? Предполагается, что это поможет нам легче писать код и лучше общаться. И ответ будет сложнее, чем сложнее он становится, тем лучше будет продажа фреймворка.
Угловая инъекция дает нам первый намек в достижении этого заключения.
«$ injector используется для извлечения экземпляров объекта, как определено поставщиком », не службой, не фабрикой, а провайдером.
И лучшим ответом было бы следующее: «Служба Angular создается фабрикой сервисов. Эти фабрики сервисов являются функциями, которые, в свою очередь, создаются поставщиком услуг. Поставщики услуг являются функциями конструктора. При реализации они должны содержать свойство называется $ get, который содержит функцию фабрики сервиса. "
Так что мастер провайдер и инжектор и все встанет на свои места :). И в Typescript становится интересным, когда $ get может быть реализован в провайдере путем наследования от IServiceProvider.
источник