Я видел как angular.factory (), так и angular.service (), используемые для объявления сервисов; Однако я не могу найти angular.service
нигде в официальной документации.
В чем разница между этими двумя методами?
Что следует использовать для чего (при условии, что они делают разные вещи)?
angularjs
angular-services
Джекоб
источник
источник
Ответы:
У меня были проблемы с обдумыванием этой концепции, пока я не сформулировал это для себя таким образом:
Сервис : функция, которую вы пишете, будет новой -ed:
Factory : функция (конструктор), которую вы пишете, будет вызвана :
То, что вы делаете с этим, зависит от вас, но есть несколько полезных шаблонов ...
Например, написание сервисной функции для предоставления публичного API:
Или используя фабричную функцию для предоставления общедоступного API:
Или используя фабричную функцию для возврата конструктора:
Какой использовать? ...
Вы можете сделать то же самое с обоими. Однако в некоторых случаях фабрика предоставляет вам немного больше гибкости для создания инъекций с более простым синтаксисом. Это потому, что, хотя myInjectedService всегда должен быть объектом, myInjectedFactory может быть объектом, ссылкой на функцию или любым значением вообще. Например, если вы написали сервис для создания конструктора (как в последнем примере выше), его необходимо создать, например, так:
что, возможно, менее желательно, чем это:
(Но вы должны быть осторожны с использованием этого типа шаблона в первую очередь, потому что новые объекты -ing в ваших контроллерах создают трудно отслеживаемые зависимости, которые трудно смоделировать для тестирования. Лучше иметь службу, управляющую коллекцией объектов для Вы чем пользуетесь
new()
коварно.)Еще одна вещь, они все синглтоны ...
Также имейте в виду, что в обоих случаях angular помогает вам управлять одиночкой. Независимо от того, где и сколько раз вы вводите свой сервис или функцию, вы получите одну и ту же ссылку на один и тот же объект или функцию. (За исключением случая, когда фабрика просто возвращает значение, такое как число или строка. В этом случае вы всегда получите одно и то же значение, но не ссылку.)
источник
new fn()
, поэтому они должны возвращать экземпляр.Проще говоря ..
источник
Вот основные отличия:
Сервисы
Синтаксис:
module.service( 'serviceName', function );
Результат: при объявлении serviceName в качестве вводимого аргумента вам будет предоставлен экземпляр функции, переданной в
module.service
.Использование: Может быть полезно для совместного использования служебных функций , которые полезно вызывать, просто добавляя
( )
ссылку на введенную функцию. Может также работать сinjectedArg.call( this )
или аналогичным.Заводы
Синтаксис:
module.factory( 'factoryName', function );
Результат: при объявлении factoryName в качестве вводимого аргумента вам будет предоставлено значение, возвращаемое путем вызова ссылки на функцию, переданной в
module.factory
.Использование: Может быть полезно для возврата функции 'class', которая затем может быть new'ed для создания экземпляров.
Вот пример использования сервисов и фабрики . Узнайте больше о AngularJS Service vs Factory .
Вы также можете проверить документацию AngularJS и аналогичный вопрос о стековом потоке, перепутанный с сервисом против фабрики .
источник
$providers
все время.this.myFunc = function(){}
в своем сервисе (избавляет вас от написания кода для создания объекта, как вы должны делать с фабрикой ).TL; DR
1) Когда вы используете Factory, вы создаете объект, добавляете к нему свойства, а затем возвращаете тот же объект. Когда вы передадите эту фабрику в свой контроллер, эти свойства объекта теперь будут доступны в этом контроллере через вашу фабрику.
2) Когда вы используете Сервис , Angular создает его за кулисами с ключевым словом «new». Из-за этого вы добавите свойства в «this», и сервис вернет «this». Когда вы передаете услугу в свой контроллер, эти свойства в «this» теперь будут доступны на этом контроллере через ваш сервис.
Не TL; DR
1)
Фабрики - это самый популярный способ создания и настройки сервиса. Там действительно не намного больше, чем то, что сказал TL; DR. Вы просто создаете объект, добавляете к нему свойства, а затем возвращаете тот же объект. Затем, когда вы передадите фабрику в свой контроллер, эти свойства объекта теперь будут доступны в этом контроллере через вашу фабрику. Более подробный пример приведен ниже.
Теперь любые свойства, которые мы прикрепляем к «сервису», будут нам доступны, когда мы передадим «myFactory» в наш контроллер.
Теперь давайте добавим некоторые «приватные» переменные в нашу функцию обратного вызова. Они не будут напрямую доступны из контроллера, но мы в конечном итоге настроим некоторые методы получения / установки для «службы», чтобы иметь возможность изменять эти «частные» переменные при необходимости.
Здесь вы заметите, что мы не привязываем эти переменные / функцию к 'service'. Мы просто создаем их, чтобы потом использовать или модифицировать их.
Теперь, когда наши вспомогательные / закрытые переменные и функции на месте, давайте добавим некоторые свойства к объекту 'service'. Что бы мы ни ставили на «сервис», мы сможем напрямую использовать тот контроллер, в который мы передаем «myFactory».
Мы собираемся создать методы setArtist и getArtist, которые просто возвращают или устанавливают художника. Мы также собираемся создать метод, который будет вызывать iTunes API с нашим созданным URL. Этот метод возвращает обещание, которое будет выполнено, как только данные вернутся из iTunes API. Если у вас не было большого опыта использования обещаний в Angular, я настоятельно рекомендую глубоко погрузиться в них.
Ниже 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. Это в основном пример кода вышеупомянутого абзаца. Я поместил «представление интерпретатора» или то, как интерпретатор видит код внутри заметок.
Теперь, имея представление о том, что на самом деле делает ключевое слово «new» в JavaScript, создание службы в Angular должно быть проще для понимания.
Самая важная вещь, которую нужно понять при создании Сервиса, это знание того, что Сервисы создаются с помощью ключевого слова «new». Объединяя эти знания с нашими примерами выше, вы теперь должны понимать, что вы будете привязывать свои свойства и методы непосредственно к «this», которое затем будет возвращено из самой Службы. Давайте посмотрим на это в действии.
В отличие от того, что мы изначально делали с примером Factory, нам не нужно создавать объект, а затем возвращать этот объект, потому что, как упоминалось много раз ранее, мы использовали ключевое слово «new», поэтому интерпретатор создаст этот объект, предоставив ему делегирование это прототип, а затем верните его нам без необходимости выполнять работу.
Прежде всего, давайте создадим нашу «приватную» и вспомогательную функцию. Это должно выглядеть очень знакомо, так как мы сделали то же самое с нашим заводом. Я не буду объяснять, что здесь делает каждая строка, потому что я сделал это в заводском примере, если вы не уверены, перечитайте заводской пример.
Теперь мы прикрепим все наши методы, которые будут доступны в нашем контроллере, к «this».
Теперь, как и на нашей фабрике, setArtist, getArtist и callItunes будут доступны в любом контроллере, в который мы передаем myService. Вот контроллер myService (который почти такой же, как наш заводской контроллер).
Как я уже упоминал ранее, когда вы действительно понимаете, что делает «новое», Сервисы практически идентичны фабрикам в Angular.
источник
Ключ в названии
Услуги и фабрики похожи друг на друга. Оба будут давать одноэлементный объект, который может быть введен в другие объекты, и поэтому часто используются взаимозаменяемо.
Они предназначены для семантического использования для реализации различных шаблонов проектирования.
Сервисы для реализации сервисного шаблона
Шаблон службы - это шаблон, в котором ваше приложение разбито на логически согласованные единицы функциональности. Примером может быть средство доступа API или набор бизнес-логики.
Это особенно важно в Angular, потому что Angular модели, как правило, представляют собой просто объекты JSON, извлеченные с сервера, и поэтому нам нужно где-то разместить нашу бизнес-логику.
Вот сервис Github, например. Он умеет разговаривать с Github. Он знает о URL и методах. Мы можем внедрить его в контроллер, и он сгенерирует и вернет обещание.
Фабрики реализуют фабричный образец
Фабрики, с другой стороны, предназначены для реализации фабричного образца. Фабричный шаблон, в котором мы используем фабричную функцию для генерации объекта. Обычно мы можем использовать это для построения моделей. Вот фабрика, которая возвращает конструктор Author:
Мы бы использовали это так:
Обратите внимание, что фабрики также возвращают синглтоны.
Фабрики могут вернуть конструктор
Поскольку фабрика просто возвращает объект, она может вернуть любой тип объекта, который вам нравится, включая функцию конструктора, как мы видели выше.
Фабрики возвращают объект; услуги являются новыми
Другое техническое отличие состоит в том, как складываются услуги и фабрики. Сервисная функция будет обновлена для создания объекта. Будет вызвана фабричная функция, которая вернет объект.
Это означает, что в сервисе мы добавляем «this», которое в контексте конструктора будет указывать на строящийся объект.
Чтобы проиллюстрировать это, вот тот же простой объект, созданный с использованием сервиса и фабрики:
источник
Author
должен быть параметр инжектораPerson
.Все ответы здесь, похоже, касаются обслуживания и фабрики, и это действительно так, потому что об этом спрашивали. Но это также важно иметь в виду , что есть несколько других , включая
provider()
,value()
иconstant()
.Ключ для запоминания заключается в том, что каждый из них является частным случаем другого. Каждый особый случай в цепочке позволяет вам делать то же самое с меньшим количеством кода. Каждый из них также имеет некоторые дополнительные ограничения.
Чтобы решить, когда использовать, который вы видите, какой из них позволяет вам делать то, что вы хотите в меньшем количестве кода. Вот изображение, иллюстрирующее, насколько они похожи:
Для полной пошаговой разбивки и быстрого ознакомления с тем, когда использовать каждый, вы можете посетить блог, где я получил это изображение:
http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/
источник
app.factory ('fn', fn) против app.service ('fn', fn)
строительство
На фабриках Angular вызовет функцию, чтобы получить результат. Это результат, который кэшируется и вводится.
С сервисами Angular будет вызывать функцию конструктора, вызывая new . Построенная функция кэшируется и вводится.
Реализация
Фабрики обычно возвращают литерал объекта, потому что возвращаемое значение - это то, что вводится в контроллеры, блоки выполнения, директивы и т. Д.
Сервисные функции обычно ничего не возвращают. Вместо этого они выполняют инициализацию и предоставляют функции. Функции также могут ссылаться на «this», поскольку он был создан с использованием «new».
Вывод
Когда дело доходит до использования заводов или услуг, они оба очень похожи. Они внедряются в контроллеры, директивы, блоки выполнения и т. Д. И используются в клиентском коде почти таким же образом. Они также являются синглетонами - это означает, что один и тот же экземпляр является общим для всех мест, где вводится сервис / фабрика.
Итак, что вы предпочитаете? Либо один - они настолько похожи, что различия тривиальны. Если вы выбираете одно над другим, просто знайте, как они построены, чтобы вы могли правильно их реализовать.
источник
Я провел некоторое время, пытаясь выяснить разницу.
И я думаю, что фабричная функция использует шаблон модуля, а сервисная функция использует стандартный шаблон конструктора сценариев Java.
источник
Фабричный шаблон является более гибким, поскольку он может возвращать функции и значения, а также объекты.
ИМХО, в шаблоне обслуживания нет особого смысла, так как все, что он делает, вы можете легко сделать на фабрике. Исключения могут быть:
Можно утверждать, что шаблон службы - это немного более приятный способ создания нового объекта с точки зрения синтаксиса, но его создание также более затратно. Другие указали, что angular использует «new» для создания сервиса, но это не совсем так - он не может этого сделать, потому что каждый конструктор сервиса имеет разное количество параметров. На самом деле Angular использует внутренний шаблон фабрики, чтобы обернуть вашу функцию конструктора. Затем он делает несколько хитрых покерных манипуляций для имитации «нового» оператора javascript, вызывая ваш конструктор с переменным числом вводимых аргументов - но вы можете пропустить этот шаг, если вы просто используете фабричный шаблон напрямую, таким образом, очень немного увеличивая эффективность вашего код.
источник
function MyFactory(dep1) { var $$foo = 'bar', factory = {}; Object.defineProperties(factory.prototype, { foo: { value: $$foo } }); return factory; }
function MyService(dep1) { var $$foo = 'bar'; Object.defineProperties(MyService.prototype, { foo: { value: $$foo } }); }
Хотя и MyFactory, и MyService используют прототип, MyFactory по-прежнему испытывает снижение производительности, создавая возвращаемый объект. В обоих примерах у них есть ряды, но в MyService нет разницы в производительности.MyFactory(someArgument)
(ex$http()
). Это не возможно с услугой , как вы бы ссылающегося конструктор:MyService(someArgument)
.