Чтоже это за странные service, factory и provider. Казалось бы — выполняют почти одну и туже функцию, подключаются через DI. Зачем их так много?
На абстрактный пример можно глянуть тут (к слову, автор привел очень хороший пример).
Но никто не рассказывает, зачем оно в реальной практике нужно.
Сервис
Он чаще всего используется для создания разделяемого ресурса.
var constructor = function constructor() { this.foo = 'foo' this.bar = function bar() { } } .service('someService', constructor)
Когда сервис создается первый раз, то выполняется
var someServiceImpl = new constructor()
И в дальнейшем при подключении зависимостей через DI в объекты будет всегда передаваться someServiceImpl.
Фабрика
это более продвинутая конструкция. Она не является разделяемым ресурсом сама по себе. При каждом использовании фабрики через DI ее значение — это результат вызова фабричной функции.
var factoryFn = function () { var someClass = function() {} return someClass; } .factory('someFactory', factoryFn)
При первом инстанцировании фабрики будет вызвана функция factoryFn и ее результат — это уже и есть разделяемое между всеми участниками системы значение.
Свое применения фабрика находит в первую очередь для реализации моделей. Как в примере выше. Создается и описывается класс модели someClass и фабрика при инстанцировании возвращает ссылку на него. В последующем можно использовать этот класс как конструктор объектов.
.controller('someController', ['someFactory', function(someFactory) { // Тут мы успешно инстанцируем новый объект someClass var someClassImpl = new someFactory(); }])
Провайдер
Это тоже фабрика. Но более продвинутаця. Так же точно при первом инстанцировании провайдера выполняется некая функция и ее результат становится разделяемым значением.
Но вся мощь провайдеров в том, что их можно конфигурировать (в отличие от фабрик или сервисов). Т.е. на этапе инициализации вашего приложения можно передать провайдеру некоторые опции, которые нельзя указать в дальнейшем.
Как пример — библиотека для oauth-авторизации. на этапе конфигурирования в нее передаются токены.
var providerFn = function() { var someModel = function() { // это модель } this.configure = function() { // делаем какую-то конфигурацию } this.$get = function() { return new someModel() } } .provider('someProvider', providerFn)
И теперь самое интересное: при подключении провайдера через DI в качестве разделяемого объекта будет выступать то, что вернула функция $get.
В то же время на этапе конфигурирования нам доступен сам инстанс providerFn и мы можем использовать его функционал по конфигурированияю
.config(['someProvider', function(someProvider) { //... someProvider.configure(options) }])