AngularJS: Сервис против провайдера против фабрики

Каковы различия между Service, Provider а также Factory в AngularJS?

31 ответ

Решение

Из списка рассылки AngularJS я получил удивительную ветку, в которой рассказывается о сервисе, фабрике, провайдере и их использовании. Составление ответов:

Сервисы

Синтаксис: module.service( 'serviceName', function );
Результат: при объявлении serviceName в качестве вводимого аргумента вам будет предоставлен экземпляр функции. Другими словами new FunctionYouPassedToService(),

Фабрики

Синтаксис: module.factory( 'factoryName', function );
Результат: при объявлении factoryName в качестве вводимого аргумента вам будет предоставлено значение, возвращаемое путем вызова ссылки на функцию, переданной в module.factory.

Провайдеры

Синтаксис: module.provider( 'providerName', function );
Результат: при объявлении providerName в качестве вводимого аргумента вы получите (new ProviderFunction()).$get(), Функция конструктора создается перед вызовом метода $get - ProviderFunction является ссылкой на функцию, переданную в module.provider.

Преимущество поставщиков заключается в том, что их можно настраивать на этапе настройки модуля.

Смотрите здесь для предоставленного кода.

Вот большое дальнейшее объяснение Миско:

provide.value('a', 123);

function Controller(a) {
  expect(a).toEqual(123);
}

В этом случае инжектор просто возвращает значение как есть. Но что, если вы хотите вычислить значение? Тогда используйте фабрику

provide.factory('b', function(a) {
  return a*2;
});

function Controller(b) {
  expect(b).toEqual(246);
}

Так factory это функция, которая отвечает за создание стоимости. Обратите внимание, что фабричная функция может запрашивать другие зависимости.

Но что, если вы хотите быть более интересным и иметь класс под названием Greeter?

function Greeter(a) {
  this.greet = function() {
    return 'Hello ' + a;
  }
}

Тогда для создания экземпляра вам придется написать

provide.factory('greeter', function(a) {
  return new Greeter(a);
});

Тогда мы могли бы попросить "приветствовать" в контроллере, как это

function Controller(greeter) {
  expect(greeter instanceof Greeter).toBe(true);
  expect(greeter.greet()).toEqual('Hello 123');
}

Но это слишком многословно. Более короткий способ написать это будет provider.service('greeter', Greeter);

Но что, если мы хотим настроить Greeter класс до инъекции? Тогда мы могли бы написать

provide.provider('greeter2', function() {
  var salutation = 'Hello';
  this.setSalutation = function(s) {
    salutation = s;
  }

  function Greeter(a) {
    this.greet = function() {
      return salutation + ' ' + a;
    }
  }

  this.$get = function(a) {
    return new Greeter(a);
  };
});

Тогда мы можем сделать это:

angular.module('abc', []).config(function(greeter2Provider) {
  greeter2Provider.setSalutation('Halo');
});

function Controller(greeter2) {
  expect(greeter2.greet()).toEqual('Halo 123');
}

Как примечание стороны, service, factory, а также value все получены от поставщика.

provider.service = function(name, Class) {
  provider.provide(name, function() {
    this.$get = function($injector) {
      return $injector.instantiate(Class);
    };
  });
}

provider.factory = function(name, factory) {
  provider.provide(name, function() {
    this.$get = function($injector) {
      return $injector.invoke(factory);
    };
  });
}

provider.value = function(name, value) {
  provider.factory(name, function() {
    return value;
  });
};

JS Fiddle Demo

Пример " 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');
});
        

function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {
    
    $scope.hellos = [
        helloWorld.sayHello(),
        helloWorldFromFactory.sayHello(),
        helloWorldFromService.sayHello()];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
    {{hellos}}
</div>
</body>

TL;DR

1) Когда вы используете Factory, вы создаете объект, добавляете к нему свойства, а затем возвращаете тот же объект. Когда вы передадите эту фабрику в свой контроллер, эти свойства объекта теперь будут доступны в этом контроллере через вашу фабрику.

app.controller(‘myFactoryCtrl’, function($scope, myFactory){
  $scope.artist = myFactory.getArtist();
});

app.factory(‘myFactory’, function(){
  var _artist = ‘Shakira’;
  var service = {};

  service.getArtist = function(){
    return _artist;
  }

  return service;
});


2) Когда вы используете Service, AngularJS создает его за кулисами с ключевым словом "new". Из-за этого вы добавите свойства в "this", и сервис вернет "this". Когда вы передаете услугу в свой контроллер, эти свойства в "this" теперь будут доступны на этом контроллере через ваш сервис.

app.controller(‘myServiceCtrl’, function($scope, myService){
  $scope.artist = myService.getArtist();
});

app.service(‘myService’, function(){
  var _artist = ‘Nelly’;
  this.getArtist = function(){
    return _artist;
  }
});



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 set in config’;
});



Не TL;DR

1) Фабрика
Фабрики являются наиболее популярным способом создания и настройки сервиса. Там действительно не намного больше, чем то, что сказал TL;DR. Вы просто создаете объект, добавляете к нему свойства, а затем возвращаете тот же объект. Затем, когда вы передадите фабрику в свой контроллер, эти свойства объекта теперь будут доступны в этом контроллере через вашу фабрику. Более обширный пример приведен ниже.

app.factory(‘myFactory’, function(){
  var service = {};
  return service;
});

Теперь любые свойства, которые мы прикрепляем к "сервису", будут нам доступны, когда мы передадим "myFactory" в наш контроллер.

Теперь давайте добавим некоторые "приватные" переменные в нашу функцию обратного вызова. Они не будут напрямую доступны из контроллера, но мы в конечном итоге настроим некоторые методы получения / установки для "службы", чтобы иметь возможность изменять эти "частные" переменные при необходимости.

app.factory(‘myFactory’, function($http, $q){
  var service = {};
  var baseUrl = ‘https://itunes.apple.com/search?term=’;
  var _artist = ‘’;
  var _finalUrl = ‘’;

  var makeUrl = function(){
   _artist = _artist.split(‘ ‘).join(‘+’);
    _finalUrl = baseUrl + _artist + ‘&callback=JSON_CALLBACK’;
    return _finalUrl
  }

  return service;
});

Здесь вы заметите, что мы не привязываем эти переменные / функцию к '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 или отклоняем его с сообщением "Произошла ошибка".

app.factory('myFactory', function($http, $q){
  var service = {};
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  service.setArtist = function(artist){
    _artist = artist;
  }

  service.getArtist = function(){
    return _artist;
  }

  service.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

  return service;
});

Теперь наша фабрика завершена. Теперь мы можем внедрить 'myFactory' в любой контроллер, и тогда мы сможем вызывать наши методы, которые мы прикрепили к нашему сервисному объекту (setArtist, getArtist и callItunes).

app.controller('myFactoryCtrl', function($scope, myFactory){
  $scope.data = {};
  $scope.updateArtist = function(){
    myFactory.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myFactory.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

В вышеприведенном контроллере мы вводим в сервис myFactory. Затем мы устанавливаем свойства нашего объекта $ scope с данными из myFactory. Единственный сложный код выше, если вы никогда не имели дело с обещаниями раньше. Поскольку callItunes возвращает обещание, мы можем использовать метод.then() и устанавливать $scope.data.artistData только после того, как наше обещание будет выполнено с данными iTunes. Вы заметите, что наш контроллер очень "тонкий" (это хорошая практика кодирования). Вся наша логика и постоянные данные находятся в нашем сервисе, а не в нашем контроллере.

2) Сервис
Возможно, самая важная вещь, которую нужно знать при создании Сервиса, это то, что он создается с ключевым словом "new". Для вас, гуру Java Script, это должно дать вам подсказку о природе кода. Для тех из вас, кто имеет ограниченный опыт работы с Java Script, или тех, кто не слишком знаком с тем, что на самом деле делает ключевое слово "new", давайте рассмотрим некоторые основы Java Script, которые в конечном итоге помогут нам понять природу Сервиса.

Чтобы действительно увидеть изменения, которые происходят, когда вы вызываете функцию с ключевым словом "new", давайте создадим функцию и вызовем ее с ключевым словом "new", а затем покажем, что делает интерпретатор, когда видит ключевое слово "new". Конечные результаты будут одинаковыми.

Сначала давайте создадим наш конструктор.

var Person = function(name, age){
  this.name = name;
  this.age = age;
}

Это типичная функция конструктора Java Script. Теперь всякий раз, когда мы вызываем функцию Person с помощью ключевого слова new, this будет привязано к вновь созданному объекту.

Теперь давайте добавим метод в прототип нашего Person, чтобы он был доступен для каждого экземпляра нашего класса Person.

Person.prototype.sayName = function(){
  alert(‘My name is ‘ + this.name);
}

Теперь, поскольку мы поместили функцию sayName в прототип, каждый экземпляр Person сможет вызывать функцию sayName в порядке оповещения об имени этого экземпляра.

Теперь, когда у нас есть функция конструктора Person и наша функция sayName в ее прототипе, давайте создадим экземпляр Person, а затем вызовем функцию sayName.

var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’

Таким образом, весь код для создания конструктора Person, добавления функции к его прототипу, создания экземпляра Person и последующего вызова функции для его прототипа выглядит следующим образом.

var Person = function(name, age){
  this.name = name;
  this.age = age;
}
Person.prototype.sayName = function(){
  alert(‘My name is ‘ + this.name);
}
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’

Теперь давайте посмотрим, что на самом деле происходит, когда вы используете ключевое слово "new" в Java Script. Первое, что вы должны заметить, это то, что после использования "new" в нашем примере мы можем вызвать метод (sayName) для "tyler" так же, как если бы это был объект - это потому, что он есть. Итак, во-первых, мы знаем, что наш конструктор Person возвращает объект, видим ли мы это в коде или нет. Во-вторых, мы знаем, что, поскольку наша функция sayName расположена в прототипе, а не непосредственно в экземпляре Person, объект, который возвращает функция Person, должен делегировать своему прототипу при неудачных поисках. Проще говоря, когда мы вызываем tyler.sayName(), интерпретатор говорит: "Хорошо, я собираюсь посмотреть на только что созданный объект" tyler ", найти функцию sayName и затем вызвать ее. Подожди, я не вижу этого здесь - все, что я вижу, это имя и возраст, позволь мне проверить прототип. Да, похоже, что это на прототипе, позвольте мне назвать это ".

Ниже приведен код того, как вы можете думать о том, что на самом деле делает ключевое слово "новый" в Java Script. Это в основном пример кода вышеупомянутого абзаца. Я поместил "представление интерпретатора" или то, как интерпретатор видит код внутри заметок.

var Person = function(name, age){
  //The below line creates an object(obj) that will delegate to the person’s prototype on failed lookups.
  //var obj = Object.create(Person.prototype);

  //The line directly below this sets ‘this’ to the newly created object
  //this = obj;

  this.name = name;
  this.age = age;

  //return this;
}

Теперь, имея представление о том, что на самом деле делает ключевое слово "new" в Java Script, создание сервиса в AngularJS должно быть проще для понимания.

Самая важная вещь, которую нужно понять при создании Сервиса, это знание того, что Сервисы создаются с помощью ключевого слова "new". Объединяя эти знания с нашими примерами выше, вы должны теперь признать, что вы будете привязывать свои свойства и методы непосредственно к "this", которое затем будет возвращено из самой Службы. Давайте посмотрим на это в действии.

В отличие от того, что мы изначально делали с примером Factory, нам не нужно создавать объект, а затем возвращать этот объект, потому что, как упоминалось много раз ранее, мы использовали ключевое слово "new", поэтому интерпретатор создаст этот объект, предоставив ему делегирование это прототип, а затем верните его нам без необходимости выполнять работу.

Прежде всего, давайте создадим нашу "приватную" и вспомогательную функцию. Это должно выглядеть очень знакомо, так как мы сделали то же самое с нашим заводом. Я не буду объяснять, что здесь делает каждая строка, потому что я сделал это в заводском примере, если вы не уверены, перечитайте заводской пример.

app.service('myService', function($http, $q){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }
});

Теперь мы прикрепим все наши методы, которые будут доступны в нашем контроллере, к "this".

app.service('myService', function($http, $q){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  this.setArtist = function(artist){
    _artist = artist;
  }

  this.getArtist = function(){
    return _artist;
  }

  this.callItunes = function(){
    makeUrl();
    var deferred = $q.defer();
    $http({
      method: 'JSONP',
      url: _finalUrl
    }).success(function(data){
      deferred.resolve(data);
    }).error(function(){
      deferred.reject('There was an error')
    })
    return deferred.promise;
  }

});

Теперь, как и на нашей фабрике, setArtist, getArtist и callItunes будут доступны в любом контроллере, в который мы передаем myService. Вот контроллер myService (который почти такой же, как наш заводской контроллер).

app.controller('myServiceCtrl', function($scope, myService){
  $scope.data = {};
  $scope.updateArtist = function(){
    myService.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myService.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }
});

Как я уже упоминал ранее, когда вы действительно понимаете, что делает "новое", Сервисы практически идентичны фабрикам в AngularJS.

3) Провайдер

Самое важное, что нужно помнить о провайдерах, это то, что они являются единственной службой, которую вы можете передать в часть app.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 в этот конкретный контроллер.

При создании службы с провайдером единственными свойствами / методами, которые будут доступны в вашем контроллере, являются те свойства / методы, которые возвращаются из функции $get(). Приведенный ниже код помещает $ get в this (которое, как мы знаем, в конечном итоге будет возвращено из этой функции). Теперь эта функция $ get возвращает все методы / свойства, которые мы хотим быть доступными в контроллере. Вот пример кода.

this.$get = function($http, $q){
    return {
      callItunes: function(){
        makeUrl();
        var deferred = $q.defer();
        $http({
          method: 'JSONP',
          url: _finalUrl
        }).success(function(data){
          deferred.resolve(data);
        }).error(function(){
          deferred.reject('There was an error')
        })
        return deferred.promise;
      },
      setArtist: function(artist){
        _artist = artist;
      },
      getArtist: function(){
        return _artist;
      },
      thingOnConfig: this.thingFromConfig
    }
  }

Теперь полный код провайдера выглядит следующим образом

app.provider('myProvider', function(){
  var baseUrl = 'https://itunes.apple.com/search?term=';
  var _artist = '';
  var _finalUrl = '';

  //Going to set this property on the config function below
  this.thingFromConfig = '';

  var makeUrl = function(){
    _artist = _artist.split(' ').join('+');
    _finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
    return _finalUrl;
  }

  this.$get = function($http, $q){
    return {
      callItunes: function(){
        makeUrl();
        var deferred = $q.defer();
        $http({
          method: 'JSONP',
          url: _finalUrl
        }).success(function(data){
          deferred.resolve(data);
        }).error(function(){
          deferred.reject('There was an error')
        })
        return deferred.promise;
      },
      setArtist: function(artist){
        _artist = artist;
      },
      getArtist: function(){
        return _artist;
      },
      thingOnConfig: this.thingFromConfig
    }
  }
});

Теперь, как и на нашей фабрике, Service, setArtist, getArtist и callItunes будут доступны в любом контроллере, в который мы передаем myProvider. Вот контроллер myProvider (который почти такой же, как наш заводской / сервисный контроллер).

app.controller('myProviderCtrl', function($scope, myProvider){
  $scope.data = {};
  $scope.updateArtist = function(){
    myProvider.setArtist($scope.data.artist);
  };

  $scope.submitArtist = function(){
    myProvider.callItunes()
      .then(function(data){
        $scope.data.artistData = data;
      }, function(data){
        alert(data);
      })
  }

  $scope.data.thingFromConfig = myProvider.thingOnConfig;
});

Как упоминалось ранее, весь смысл создания службы с помощью 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, это будет "Это предложение было установлено…".

Все Сервисы являются одиночными; они создаются один раз за приложение. Они могут быть любого типа, будь то примитив, литерал объекта, функция или даже экземпляр пользовательского типа.

value, factory, service, constant, а также provider методы все провайдеры. Они учат Инжектора, как создавать Услуги.

Наиболее многословным, но и наиболее полным является рецепт провайдера. Остальные четыре типа рецептов - Value, Factory, Service и Constant - просто синтаксический сахар поверх рецепта поставщика.

  • Рецепт значения - это простейший случай, когда вы сами создаете экземпляр Сервиса и указываете значение для инжектора.
  • Фабричный рецепт дает Injector заводскую функцию, которую он вызывает, когда ему нужно создать экземпляр службы. При вызове фабричная функция создает и возвращает экземпляр службы. Зависимости Сервиса вводятся как аргументы функций. Таким образом, использование этого рецепта добавляет следующие способности:
    • Возможность использования других сервисов (есть зависимости)
    • Служба инициализации
    • Отложенная / ленивая инициализация
  • Рецепт Service почти такой же, как и Factory, но здесь Injector вызывает конструктор с оператором new вместо фабричной функции.
  • Рецепт провайдера, как правило, излишним. Он добавляет еще один уровень косвенности, позволяя настроить создание фабрики.

    Вы должны использовать рецепт провайдера только в том случае, если вы хотите предоставить API для конфигурации всего приложения, которую необходимо выполнить до запуска приложения. Обычно это интересно только для многоразовых сервисов, поведение которых может немного отличаться в разных приложениях.

  • Рецепт Constant точно так же, как и рецепт Value, за исключением того, что он позволяет вам определять сервисы, доступные на этапе конфигурации. Раньше, чем сервисы, созданные с использованием рецепта Value. В отличие от ценностей, они не могут быть оформлены с использованием decorator,
Смотрите документацию поставщика.

Понимание AngularJS Фабрика, Сервис и Поставщик

Все они используются для совместного использования одноразовых объектов. Это помогает обмениваться повторно используемым кодом через ваше приложение / различные компоненты / модули.

Из Документов Сервис / Фабрика:

  • Ленивый экземпляр - Angular создает экземпляр сервиса / фабрики только тогда, когда от него зависит компонент приложения.
  • Singletons - каждый компонент, зависящий от сервиса, получает ссылку на один экземпляр, сгенерированный фабрикой сервисов.

завод

Фабрика - это функция, в которой вы можете манипулировать / добавлять логику перед созданием объекта, после чего возвращается вновь созданный объект.

app.factory('MyFactory', function() {
    var serviceObj = {};
    //creating an object with methods/functions or variables
    serviceObj.myFunction = function() {
        //TO DO:
    };
    //return that object
    return serviceObj;
});

использование

Это может быть просто набор функций, таких как класс. Следовательно, он может быть создан в разных контроллерах, когда вы вводите его в функции контроллера / фабрики / директивы. Он создается только один раз за приложение.

обслуживание

Просто глядя на сервисы, подумай о прототипе массива. Сервис - это функция, которая создает новый объект, используя ключевое слово "new". Вы можете добавить свойства и функции к объекту службы, используя this ключевое слово. В отличие от фабрики, он ничего не возвращает (он возвращает объект, который содержит методы / свойства).

app.service('MyService', function() {
    //directly binding events to this context
    this.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, а сервис и фабрика - нет.

Надеюсь, что это прояснило ваше понимание Фабрики, Сервиса и Поставщика.

Для меня откровение пришло, когда я понял, что все они работают одинаково: запустив что-то один раз, сохраняя полученное значение, а затем обработав то же самое сохраненное значение, когда на него ссылаются посредством внедрения зависимостей.

Скажем, у нас есть:

app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);

Разница между тремя заключается в том, что:

  1. aсохраненное значение приходит от запуска fn,
  2. bсохраненное значение исходит от newИНГ fn,
  3. cсохраненное значение приходит от первого получения экземпляра newИНГ fn, а затем создаю $get метод экземпляра.

Это означает, что внутри AngularJS есть что-то вроде объекта кэша, значение которого для каждой инъекции присваивается только один раз, когда они были введены впервые, и где:

cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()

Вот почему мы используем this в услугах, и определить this.$get в провайдерах.

Сервис против провайдера против фабрики:

Я пытаюсь сделать это простым. Это все о базовой концепции JavaScript.

Прежде всего, давайте поговорим об услугах в AngularJS!

Что такое Сервис: В AngularJS Сервис - не что иное, как одноэлементный объект JavaScript, который может хранить некоторые полезные методы или свойства. Этот одноэлементный объект создается на основе ngApp (приложение Angular) и используется всеми контроллерами в текущем приложении. Когда Angularjs создает объект службы, он регистрирует этот объект службы с уникальным именем службы. Поэтому каждый раз, когда нам нужен экземпляр сервиса, Angular ищет в реестре это имя сервиса, и он возвращает ссылку на объект сервиса. Так что мы можем вызывать метод, обращаться к свойствам и т. Д. На объекте службы. У вас может возникнуть вопрос, можете ли вы также поместить свойства, методы в объектную область контроллеров! Так зачем вам сервисный объект? Ответы таковы: службы распределяются между несколькими контроллерами. Если вы поместите некоторые свойства / методы в объект области видимости контроллера, он будет доступен только для текущей области видимости. Но когда вы определяете методы, свойства для объекта службы, он будет доступен глобально и может быть доступен в любой области контроллера путем внедрения этой службы.

Таким образом, если имеется три области контроллера, пусть это будут controllerA, controllerB и controllerC, все они будут использовать один и тот же экземпляр службы.

<div ng-controller='controllerA'>
    <!-- controllerA scope -->
</div>
<div ng-controller='controllerB'>
    <!-- controllerB scope -->
</div>
<div ng-controller='controllerC'>
    <!-- controllerC scope -->
</div>

Как создать сервис?

AngularJS предоставляет различные методы для регистрации службы. Здесь мы сосредоточимся на трех методах: фабрика (..), сервис (..), провайдер (..);

Используйте эту ссылку для ссылки на код

Заводская функция:

Мы можем определить фабричную функцию, как показано ниже.

factory('serviceName',function fnFactory(){ return serviceInstance;})

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 object
  return data;
});

Сервисная функция:

service('serviceName',function fnServiceConstructor(){})

Это еще один способ, мы можем зарегистрировать услугу. Единственная разница заключается в том, как AngularJS пытается создать экземпляр объекта службы. На этот раз angular использует ключевое слово "new" и вызывает функцию конструктора, как показано ниже.

var serviceInstance = new fnServiceConstructor();

В функции конструктора мы можем использовать ключевое слово this для добавления свойств / методов к объекту службы. пример:

//Creating a service using the service method
var app= angular.module('myApp', []);
app.service('servicePattern',function(){
  this.firstName ='James';
  this.lastName =' Bond';
  this.greet = function(){
    console.log('My Name is '+ this.firstName + this.lastName);
  };
});

Функция провайдера:

Функция 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 provider
  this.firstName = 'Arnold ';
  this.lastName = ' Schwarzenegger' ;
  this.greetMessage = ' Welcome, This is default Greeting Message' ;
  //adding some method which we can call in app.config() function
  this.setGreetMsg = function(msg){
    if(msg){
      this.greetMessage =  msg ;
    }
  };

  //We can also add a method which can change firstName and lastName
  this.$get = function(){
    var firstName = this.firstName;
    var lastName = this.lastName ;
    var greetMessage = this.greetMessage;
    var data={
       greet: function(){
         console.log('hello, ' + firstName + lastName+'! '+ greetMessage);
       }
    };
    return data ;
  };
});

app.config(
  function(providerPatternProvider){
    providerPatternProvider.setGreetMsg(' How do you do ?');
  }
);

Рабочая Демо

Резюме:


Фабрика использует фабричную функцию, которая возвращает экземпляр службы.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 будет кешировать и вводить возвращаемое значение, когда запрашивается фабрика.

Пример:

app.factory('factory', function() {
    var name = '';
    // Return value **is** the object that will be injected
    return {
        name: name;
    }
})

Использование:

app.controller('ctrl', function($scope, factory) {
     $scope.name = factory.name;
});

обслуживание

Вы даете AngularJS функцию, AngularJS вызовет new, чтобы создать ее экземпляр. Это экземпляр, который создает AngularJS, который будет кэшироваться и вставляться при запросе сервиса. Поскольку new использовался для создания экземпляра службы, ключевое слово this является действительным и относится к экземпляру.

Пример:

app.service('service', function() {
     var name = '';
     this.setName = function(newName) {
         name = newName;
     }
     this.getName = function() {
         return name;
     }
});

Использование:

app.controller('ctrl', function($scope, service) {
   $scope.name = service.getName();
});

поставщик

Вы даете AngularJS функцию, и AngularJS вызовет ее $get функция. Это возвращаемое значение из $get функция, которая будет кэшироваться и вставляться при запросе сервиса.

Провайдеры позволяют вам настроить провайдера до того, как AngularJS вызовет $get способ получить инъекцию.

Пример:

app.provider('provider', function() {
     var name = '';
     this.setName = function(newName) {
          name = newName;
     }
     this.$get = function() {
         return {
            name: name
         }
     }
})

Использование (как инъекция в контроллере)

app.controller('ctrl', function($scope, provider) {
    $scope.name = provider.name;
});

Использование (настройка провайдера перед $get вызывается для создания инъекционного)

app.config(function(providerProvider) {
    providerProvider.setName('John');
});

Я заметил кое-что интересное, играя с провайдерами.

Видимость инъекционных препаратов различна для поставщиков, чем для служб и предприятий. Если вы объявите AngularJS "константой" (например, myApp.constant('a', 'Robert');), вы можете внедрить его в службы, фабрики и поставщиков.

Но если вы объявите AngularJS "значение" (например, myApp.value('b', {name: 'Jones'});), вы можете внедрить его в службы и фабрики, но НЕ в функцию создания провайдера. Вы можете, однако, ввести его в $get функция, которую вы определяете для своего провайдера. Это упоминается в документации AngularJS, но это легко пропустить. Вы можете найти его на странице%provide в разделах о методах value и constant.

http://jsfiddle.net/R2Frv/1/

<div ng-app="MyAppName">
    <div ng-controller="MyCtrl">
        <p>from Service: {{servGreet}}</p>
        <p>from Provider: {{provGreet}}</p>
    </div>
</div>
<script>
    var myApp = angular.module('MyAppName', []);

    myApp.constant('a', 'Robert');
    myApp.value('b', {name: 'Jones'});

    myApp.service('greetService', function(a,b) {
        this.greeter = 'Hi there, ' + a + ' ' + b.name;
    });

    myApp.provider('greetProvider', function(a) {
        this.firstName = a;
        this.$get = function(b) {
            this.lastName = b.name;
            this.fullName = this.firstName + ' ' + this.lastName;
            return this;
        };
    });

    function MyCtrl($scope, greetService, greetProvider) {
        $scope.servGreet = greetService.greeter;
        $scope.provGreet = greetProvider.fullName;
    }
</script>

Это очень запутанная часть для новичка, и я попытался объяснить это в простых словах

Служба AngularJS: используется для совместного использования служебных функций со ссылкой на службу в контроллере. Сервис по своей природе является одноэлементным, поэтому для одного сервиса в браузере создается только один экземпляр, и на всей странице используется одна и та же ссылка.

В сервисе мы создаем имена функций как свойство с этим объектом.

AngularJS Factory: назначение Factory также совпадает с Service, однако в этом случае мы создаем новый объект и добавляем функции в качестве свойств этого объекта, а в конце возвращаем этот объект.

Поставщик AngularJS: цель этого снова та же, однако поставщик предоставляет вывод своей функции $ get.

Определение и использование Сервиса, Фабрики и Поставщика объясняются по адресу http://www.dotnetfunda.com/articles/show/3156/difference-between-angularjs-service-factory-and-provider

Для меня лучший и самый простой способ понять разницу это:

var service, factory;
service = factory = function(injection) {}

Как AngularJS создает конкретные компоненты (упрощенно):

// service
var angularService = new service(injection);

// factory
var angularFactory = factory(injection);

Таким образом, для службы то, что становится компонентом AngularJS, является экземпляром объекта класса, который представлен функцией объявления службы. Для фабрики это результат, возвращаемый функцией объявления фабрики. Фабрика может вести себя так же, как сервис:

var factoryAsService = function(injection) {
  return new function(injection) {
    // Service content
  }
}

Самый простой способ мышления следующий:

  • Сервис - это экземпляр объекта-одиночки. Используйте сервисы, если вы хотите предоставить одноэлементный объект для вашего кода.
  • Фабрика это класс. Используйте фабрики, если вы хотите предоставить пользовательские классы для своего кода (это нельзя сделать с помощью сервисов, потому что они уже созданы).

Пример фабричного "класса" приведен в комментариях, а также о разнице поставщиков.

Мои разъяснения по этому вопросу:

В основном все упомянутые типы (сервис, фабрика, поставщик и т. Д.) Просто создают и настраивают глобальные переменные (которые, конечно, являются глобальными для всего приложения), как это делали устаревшие глобальные переменные.

Хотя глобальные переменные не рекомендуются, реальное использование этих глобальных переменных заключается в обеспечении внедрения зависимостей путем передачи переменной соответствующему контроллеру.

Существует много уровней сложности при создании значений для "глобальных переменных":

  1. постоянная
    Это определяет фактическую константу, которая не должна изменяться в течение всего приложения, как и константы в других языках (чего нет в JavaScript).
  2. Значение
    Это изменяемое значение или объект, и он служит некоторой глобальной переменной, которую можно даже внедрить при создании других служб или фабрик (см. Далее). Однако это должно быть " буквальное значение ", что означает, что нужно выписать фактическое значение и не может использовать какую-либо логику вычислений или программирования (другими словами, 39 или myText или {prop: "value"} в порядке, но 2 +2 нет).
  3. завод
    Более общее значение, которое можно вычислить сразу. Он работает путем передачи функции в AngularJS с логикой, необходимой для вычисления значения, и AngularJS выполняет ее, и сохраняет возвращаемое значение в именованной переменной.
    Обратите внимание, что можно вернуть объект (в этом случае он будет функционировать аналогично службе) или функцию (которая будет сохранена в переменной как функция обратного вызова).
  4. обслуживание
    Сервис - это более урезанная версия фабрики, которая действует только тогда, когда значение является объектом, и она позволяет писать любую логику непосредственно в функции (как если бы она была конструктором), а также объявлять и получать доступ к свойства объекта с использованием этого ключевого слова.
  5. поставщик
    В отличие от сервиса, который является упрощенной версией фабрики, провайдер является более сложным, но более гибким способом инициализации "глобальных" переменных, при этом наибольшей гибкостью является возможность установки значений из app.config.
    Это работает как использование комбинации службы и поставщика, передавая поставщику функцию, свойства которой объявлены с использованием ключевого слова this, которое можно использовать из app.config,
    Затем он должен иметь отдельную функцию $.get, которая выполняется AngularJS после установки вышеуказанных свойств через app.config file, и эта функция $.get ведет себя так же, как фабрика выше, в том смысле, что ее возвращаемое значение используется для инициализации "глобальных" переменных.

Мое понимание очень просто ниже.

Фабрика: вы просто создаете объект внутри фабрики и возвращаете его.

Обслуживание:

У вас просто есть стандартная функция, которая использует это ключевое слово для определения функции.

Поставщик:

E сть $get объект, который вы определяете, и его можно использовать для получения объекта, который возвращает данные.

Резюме из угловых документов:

  • Существует пять типов рецептов, которые определяют, как создавать объекты: Value, Factory, Service, Provider и Constant.
  • Фабрика и Сервис - наиболее часто используемые рецепты. Единственная разница между ними заключается в том, что рецепт Service лучше работает для объектов пользовательского типа, тогда как Factory может создавать примитивы и функции JavaScript.
  • Рецепт провайдера является основным типом рецепта, а все остальные являются просто синтаксическим сахаром.
  • Поставщик - самый сложный тип рецепта. Вам это не нужно, если вы не создаете многократно используемый код, который нуждается в глобальной настройке.


Лучшие ответы от SO:

/questions/28195010/smuschennyij-o-servise-protiv-fabriki/28195028#28195028 (<- ХОРОШО) https://stackru.com/a/27263882/165673
/questions/8281935/pri-sozdanii-metoda-servisa-kakaya-raznitsa-mezhdu-moduleservice-i-modulefactory/8281942#8281942

Все хорошие ответы уже. Я хотел бы добавить еще несколько пунктов на Сервис и Фабрика. Вместе с разницей между сервисом / фабрикой. И можно также иметь такие вопросы, как:

  1. Должен ли я использовать сервис или фабрику? Какая разница?
  2. Они делают то же самое или ведут себя одинаково?

Давайте начнем с разницы между обслуживанием и фабрикой:

  1. Оба являются синглетонами: всякий раз, когда Angular находит их как зависимость в первый раз, он создает один экземпляр сервиса / фабрики. Как только экземпляр создан, тот же экземпляр используется навсегда.

  2. Может использоваться для моделирования объекта с поведением: у них могут быть методы, внутренние переменные состояния и т. Д. Хотя способ написания этого кода будет отличаться.

Сервисы:

Сервис - это функция конструктора, и Angular создаст его экземпляр, вызвав new yourServiceName(), Это означает пару вещей.

  1. Функции и переменные экземпляра будут свойствами this,
  2. Вам не нужно возвращать значение. Когда Angular звонит new yourServiceName(), он получит this объект со всеми свойствами, которые вы наделили на него.

Пример примера:

angular.service('MyService', function() {
  this.aServiceVariable = "Ved Prakash"
  this.aServiceMethod = function() {
    return //code
  };
});

Когда Angular вводит это MyService сервис в контроллер, который зависит от него, этот контроллер получит MyService что он может вызывать функции, например, MyService.aServiceMethod ().

Будь осторожен с this:

Поскольку созданный сервис является объектом, методы внутри него могут ссылаться на него при вызове:

angular.service('ScoreKeeper', function($http) {
  this.score = 0;

  this.getScore = function() {
    return this.score;
  };

  this.setScore = function(newScore) {
    this.score = newScore;
  };

  this.addOne = function() {
    this.score++;
  };
});

Вы могли бы соблазниться 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 функция, вызывающая сторона получит этот объект вместо экземпляра this.

Это означает, что вы можете скопировать и вставить заводской пример снизу, заменить 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 очень похоже, и некоторые люди скажут, что любой из них в порядке. Это несколько верно, но мне легче следовать советам руководства по стилю Джона Папы и просто придерживаться заводов.**

Дополнительное уточнение заключается в том, что фабрики могут создавать функции / примитивы, а службы - нет. Проверьте это jsFiddle на основе Epokk's: http://jsfiddle.net/skeller88/PxdSP/1351/.

Фабрика возвращает функцию, которую можно вызвать:

myApp.factory('helloWorldFromFactory', function() {
  return function() {
    return "Hello, World!";
  };
});

Фабрика может также вернуть объект с методом, который может быть вызван:

myApp.factory('helloWorldFromFactory', function() {
  return {
    sayHello: function() {
      return "Hello, World!";
    }
  };
});

Служба возвращает объект с методом, который может быть вызван:

myApp.service('helloWorldFromService', function() {
  this.sayHello = function() {
     return "Hello, World!";
  };
});

Для получения дополнительной информации см. Сообщение, которое я написал о разнице: http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/

Уже есть хорошие ответы, но я просто хочу поделиться этим.

Прежде всего: поставщик является способом / рецептом для создания service (одноэлементный объект), который, как предполагается, вводится с помощью инжектора $ (как AngulaJS использует шаблон IoC).

И Value, Factory, Service и Constant (4 способа) - синтаксический сахар по сравнению с Provider way / recepie.

Есть Service vs Factory часть была покрыта: https://www.youtube.com/watch?v=BLzNCkPn3ao

Сервис это все о new Ключевое слово, которое, как мы знаем, делает 4 вещи:

  1. создает новый объект
  2. связывает это с его prototype объект
  3. подключает context в this
  4. и возвращается this

А Factory - это все о Factory Pattern - она ​​содержит функции, которые возвращают объекты, подобные этой службе.

  1. возможность использования других сервисов (есть зависимости)
  2. инициализация сервиса
  3. отложенная / ленивая инициализация

И это простое / короткое видео: охватывает также провайдера: https://www.youtube.com/watch?v=HvTZbQ_hUZY (там, на котором вы видите, видно, как они идут от фабрики к провайдеру)

Рецептпровайдера используется в основном в конфигурации приложения, до того как приложение полностью запустится / инициализируется.

После прочтения всех этих постов это создало больше путаницы для меня.. Но все же все это полезная информация.. наконец я нашел следующую таблицу, которая даст информацию с простым сравнением

  • Инжектор использует рецепты для создания объектов двух типов: сервисов и объектов специального назначения.
  • Существует пять типов рецептов, которые определяют, как создавать объекты: Value, Factory, Service, Provider и Constant.
  • Фабрика и Сервис - наиболее часто используемые рецепты. Единственная разница между ними заключается в том, что рецепт Service лучше работает для объектов пользовательского типа, тогда как Factory может создавать примитивы и функции JavaScript.
  • Рецепт провайдера является основным типом рецепта, а все остальные являются просто синтаксическим сахаром.
  • Поставщик - самый сложный тип рецепта. Вам это не нужно, если вы не создаете многократно используемый код, который нуждается в глобальной настройке.
  • Все объекты специального назначения, за исключением контроллера, определяются с помощью заводских рецептов.

И для начинающего понять:- Это может не исправить вариант использования, но на высоком уровне это то, что сценарий использования для этих трех.

  1. Если вы хотите использовать в модуле конфигурации угловой модуль должен быть создан в качестве поставщика

angular.module('myApp').config(function($testProvider){
$testProvider.someFunction();
})

  1. Ajax call или сторонние интеграции должны быть сервисными.
  2. Для манипулирования данными создайте его как фабрику

Для базовых сценариев фабрика и сервис ведут себя одинаково.

Вот пример кода, который я придумал как шаблон кода для фабрики объектов в 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 in
                            if (value === undefined) {
                                // and a default value was specified
                                if (defaultValue !== undefined) {
                                    // use the specified default value
                                    value = defaultValue;
                                } else {
                                    // otherwise use the class.prototype.defaults value
                                    value = this.defaults[key];
                                } // end if/else
                            } // end if
                        } // end if

                        // update 
                        this[key] = value;

                        // return reference to this object (fluent)
                        return this;

                    }; // end this.set()

                }; // end this.Car class definition

                // instance properties default values
                this.Car.prototype.defaults = {
                    color: 'yellow',
                    numberOfDoors: 2,
                    hasLeatherSeats: null,
                    hasFancyRadio: false
                };

                // instance factory method / constructor
                this.Car.prototype.instance = function(params) {
                    return new 
                        this.constructor()
                                .set('color',           params.color)
                                .set('numberOfDoors',   params.numberOfDoors)
                                .set('hasFancyRadio',   params.hasFancyRadio)
                                .set('hasLeatherSeats', params.hasLeatherSeats)
                    ;
                };

                return new this.Car();

            }) // end Factory Definition
            .controller('testCtrl', function($scope, CarFactory) {

                window.testCtrl = $scope;

                // first car, is red, uses class default for:
                // numberOfDoors, and hasLeatherSeats
                $scope.car1     = CarFactory
                                    .instance({
                                        color: 'red'
                                    })
                                ;

                // second car, is blue, has 3 doors, 
                // uses class default for hasLeatherSeats
                $scope.car2     = CarFactory
                                    .instance({
                                        color: 'blue',
                                        numberOfDoors: 3
                                    })
                                ;
                // third car, has 4 doors, uses class default for 
                // color and hasLeatherSeats
                $scope.car3     = CarFactory
                                    .instance({
                                        numberOfDoors: 4
                                    })
                                ;
                // sets an undefined variable for 'hasFancyRadio',
                // explicitly defines "true" as default when value is undefined
                $scope.hasFancyRadio = undefined;
                $scope.car3.set('hasFancyRadio', $scope.hasFancyRadio, true);

                // fourth car, purple, 4 doors,
                // uses class default for hasLeatherSeats
                $scope.car4     = CarFactory
                                    .instance({
                                        color: 'purple',
                                        numberOfDoors: 4
                                    });
                // and then explicitly sets hasLeatherSeats to undefined
                $scope.hasLeatherSeats = undefined;
                $scope.car4.set('hasLeatherSeats', $scope.hasLeatherSeats, undefined, true);

                // in console, type window.testCtrl to see the resulting objects

            });
    </script>

Вот более простой пример. Я использую несколько сторонних библиотек, которые ожидают, что объект "Позиция" будет отображать широту и долготу, но через различные свойства объекта. Я не хотел взламывать код вендора, поэтому я настроил объекты "Положение", которые я передавал.

    angular.module('app')
.factory('PositionFactory', function() {

    /**
     * BroilerPlate Object Instance Factory Definition / Example
     */
    this.Position = function() {

        // initialize instance properties 
        // (multiple properties to satisfy multiple external interface contracts)
        angular.extend(this, {
            lat         : null,
            lon         : null,
            latitude    : null,
            longitude   : null,
            coords: {
                latitude: null,
                longitude: null
            }
        });

        this.setLatitude = function(latitude) {
            this.latitude           = latitude;
            this.lat                = latitude;
            this.coords.latitude    = latitude;
            return this;
        };
        this.setLongitude = function(longitude) {
            this.longitude          = longitude;
            this.lon                = longitude;
            this.coords.longitude   = longitude;
            return this;
        };

    }; // end class definition

    // instance factory method / constructor
    this.Position.prototype.instance = function(params) {
        return new 
            this.constructor()
                    .setLatitude(params.latitude)
                    .setLongitude(params.longitude)
        ;
    };

    return new this.Position();

}) // end Factory Definition

.controller('testCtrl', function($scope, PositionFactory) {
    $scope.position1 = PositionFactory.instance({latitude: 39, longitude: 42.3123});
    $scope.position2 = PositionFactory.instance({latitude: 39, longitude: 42.3333});
}) // end controller

;

Используя в качестве ссылки эту страницу и документацию (которая, кажется, значительно улучшилась с тех пор, как я смотрел в последний раз), я собрал следующую (-ish) демонстрацию мира, в которой используются 4 из 5 вариантов провайдера; Значение, Постоянный, Заводской и полномасштабный Провайдер.

HTML:

<div ng-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>
    <button ng-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 CONSTANT
    return Math.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.
var Money = 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 currency
    this.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 value
Money.prototype.addThousandSeparator = function(value, symbol) {
   return value.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', function MoneyProvider() {

    var locale;

    // Function called by the config to set up the provider
    this.setLocale = function(value) {
        locale = value;   
    };

    // All providers need to implement a $get method which returns
    // an instance of the custom class which constitutes the service
    this.$get = function moneyFactory() {
        return new Money(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 @ runtime
    this.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 (означает, что вы не можете настроить это)

Исходный код фабрики

function factory(name, factoryFn, enforce) {
    return provider(name, {
      $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
    });
};

Делая service() он возвращает вам, предоставляя фабрику () с function что впрыскивает constructor (вернуть экземпляр конструктора, предоставленного вами в вашем сервисе) и вернуть его

Исходный код сервиса

function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
};

Таким образом, в основном в обоих случаях вы в конечном итоге получаете $ провайдера, настроенного на вашу функцию, которую вы предоставили, но вы можете дать что-то большее, чем $ get, как вы могли изначально предоставить в provider() для блока конфигурации

Я знаю много отличных ответов, но я должен поделиться своим опытом использования
1. service для большинства случаев дефолта
2. factory используется для создания службы этого конкретного экземпляра

// factory.js ////////////////////////////
(function() {
'use strict';
angular
    .module('myApp.services')
    .factory('xFactory', xFactoryImp);
xFactoryImp.$inject = ['$http'];

function xFactoryImp($http) {
    var fac = function (params) {
        this._params = params; // used for query params
    };

    fac.prototype.nextPage = function () {
        var url = "/_prc";

        $http.get(url, {params: this._params}).success(function(data){ ...
    }
    return fac;
}
})();

// service.js //////////////////////////
(function() {
'use strict';
angular
    .module('myApp.services')
    .service('xService', xServiceImp);
xServiceImp.$inject = ['$http'];

function xServiceImp($http) {  
    this._params = {'model': 'account','mode': 'list'};

    this.nextPage = function () {
        var url = "/_prc";

        $http.get(url, {params: this._params}).success(function(data){ ...
    }       
}
})();

и используя:

controller: ['xFactory', 'xService', function(xFactory, xService){

        // books = new instance of xFactory for query 'book' model
        var books = new xFactory({'model': 'book', 'mode': 'list'});

        // accounts = new instance of xFactory for query 'accounts' model
        var accounts = new xFactory({'model': 'account', 'mode': 'list'});

        // accounts2 = accounts variable
        var accounts2 = xService;
... 

Немного опоздал на вечеринку. Но я подумал, что это более полезно для тех, кто хотел бы узнать (или иметь ясность) о разработке пользовательских служб 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):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcFactory',
  function($scope, calcFactory) {
    $scope.a = 10;
    $scope.b = 20;

    $scope.doSum = function() {
      //$scope.sum = calcFactory.getSum($scope.a, $scope.b); //synchronous
      calcFactory.getSum($scope.a, $scope.b, function(r) { //aynchronous
        $scope.sum = r;
      });
    };

  }
]);

app.factory('calcFactory', ['$http', '$log',
  function($http, $log) {
    $log.log("instantiating calcFactory..");
    var oCalcService = {};

    //oCalcService.getSum = function(a,b){
    // return parseInt(a) + parseInt(b);
    //};

    //oCalcService.getSum = function(a, b, cb){
    // var s = parseInt(a) + parseInt(b);
    // cb(s);
    //};

    oCalcService.getSum = function(a, b, cb) { //using http service

      $http({
        url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
        method: 'GET'
      }).then(function(resp) {
        $log.log(resp.data);
        cb(resp.data);
      }, function(resp) {
        $log.error("ERROR occurred");
      });
    };

    return oCalcService;
  }
]);

Код для "сервисной" методологии для пользовательских сервисов (это очень похоже на "фабрику", но отличается от синтаксической точки зрения):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
 $scope.a = 10;
 $scope.b = 20;

 $scope.doSum = function(){
  //$scope.sum = calcService.getSum($scope.a, $scope.b);
  
  calcService.getSum($scope.a, $scope.b, function(r){
   $scope.sum = r;
  });  
 };

}]);

app.service('calcService', ['$http', '$log', function($http, $log){
 $log.log("instantiating calcService..");
 
 //this.getSum = function(a,b){
 // return parseInt(a) + parseInt(b);
 //};

 //this.getSum = function(a, b, cb){
 // var s = parseInt(a) + parseInt(b);
 // cb(s);
 //};

 this.getSum = function(a, b, cb){
  $http({
   url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
   method: 'GET'
  }).then(function(resp){
   $log.log(resp.data);
   cb(resp.data);
  },function(resp){
   $log.error("ERROR occurred");
  });
 };

}]);

Код для методологии "провайдера" для пользовательских сервисов (это необходимо, если вы хотите разработать сервис, который можно настроить):

var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
 $scope.a = 10;
 $scope.b = 20;

 $scope.doSum = function(){
  //$scope.sum = calcService.getSum($scope.a, $scope.b);
  
  calcService.getSum($scope.a, $scope.b, function(r){
   $scope.sum = r;
  });  
 };

}]);

app.provider('calcService', function(){

 var baseUrl = '';

 this.config = function(url){
  baseUrl = url;
 };

 this.$get = ['$log', '$http', function($log, $http){
  $log.log("instantiating calcService...")
  var oCalcService = {};

  //oCalcService.getSum = function(a,b){
  // return parseInt(a) + parseInt(b);
  //};

  //oCalcService.getSum = function(a, b, cb){
  // var s = parseInt(a) + parseInt(b);
  // cb(s); 
  //};

  oCalcService.getSum = function(a, b, cb){

   $http({
    url: baseUrl + '/Sum?a=' + a + '&b=' + b,
    method: 'GET'
   }).then(function(resp){
    $log.log(resp.data);
    cb(resp.data);
   },function(resp){
    $log.error("ERROR occurred");
   });
  };  

  return oCalcService;
 }];

});

app.config(['calcServiceProvider', function(calcServiceProvider){
 calcServiceProvider.config("http://localhost:4467");
}]);

Наконец, пользовательский интерфейс, который работает с любым из вышеперечисленных сервисов:

<html>
<head>
 <title></title>
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js" ></script>
 <script type="text/javascript" src="t03.js"></script>
</head>
<body ng-app="app">
 <div ng-controller="emp">
  <div>
   Value of a is {{a}},
   but you can change
   <input type=text ng-model="a" /> <br>

   Value of b is {{b}},
   but you can change
   <input type=text ng-model="b" /> <br>

  </div>
  Sum = {{sum}}<br>
  <button ng-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 files

function ServiceExampleController(NameOfTheService){
     serviceExampleController = this;
     serviceExampleController.data = NameOfTheService.getSomeData();
 }

function NameOfTheService(){
     nameOfTheService = this;
     nameOfTheService.data = "Some Data";
     nameOfTheService.getSomeData = function(){
           return nameOfTheService.data;
     }     
}

index.html

<div ng-controller = "ServiceExampleController as serviceExample">
   {{serviceExample.data}}
</div>

Особенности сервиса:

  1. Ленивый экземпляр: если он не введен, он никогда не будет создан. Таким образом, чтобы использовать его, придется ввести его в модуль.
  2. 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 function
function NameOfTheFactoryOne(){
   var factory = function(){
      return new SomeService();
    }
   return factory;
}

//second implementation where an object literal would be returned
function NameOfTheFactoryTwo(){
   var factory = {
      getSomeService : function(){
          return new SomeService();
       }
    };
   return factory;
}

Теперь с помощью двух выше в контроллере:

 var factoryOne = NameOfTheFactoryOne() //since it returns a function
 factoryOne.someMethod();

 var factoryTwo = NameOfTheFactoryTwo.getSomeService(); //accessing the object
 factoryTwo.someMethod();

Особенности Фабрики:

  1. Следует шаблону фабричного дизайна. Фабрика - это центральное место, которое производит новые объекты или функции.
  2. Производит не только синглтон, но и настраиваемые сервисы.
  3. .service() Метод - это фабрика, которая всегда производит один и тот же тип сервиса, который является одноэлементным, и без какого-либо простого способа настроить его поведение. Тот .service() Метод обычно используется как ярлык для чего-то, что не требует какой-либо настройки.

ПРОВАЙДЕР

Давайте снова посмотрим на синтаксис первым:

angular.module('ProviderModule', [])
.controller('ProviderModuleController', ProviderModuleController)
.provider('ServiceProvider', ServiceProvider)
.config(Config); //optional

Config.$inject = ['ServiceProvider'];
function Config(ServiceProvider) {
  ServiceProvider.defaults.maxItems = 10; //some default value
}


ProviderModuleController.$inject = ['ServiceProvider'];
function ProviderModuleController(ServiceProvider) {
  //some methods
}

function ServiceProvider() {
  var provider = this;

  provider.defaults = {
    maxItems: 10
  };

  provider.$get = function () {
    var someList = new someListService(provider.defaults.maxItems);

    return someList;
  };
}

}

Особенности провайдера:

  1. Провайдер - самый гибкий способ создания сервисов в Angular.
  2. Мы не только можем создать фабрику, которая динамически настраивается, но во время использования фабрики с помощью метода провайдера мы могли настраивать фабрику только один раз при начальной загрузке всего нашего приложения.
  3. Завод может быть использован во всем приложении с пользовательскими настройками. Другими словами, мы можем настроить эту фабрику до запуска приложения. Фактически в угловой документации упоминается, что метод провайдера - это то, что фактически выполняется за кулисами, когда мы настраиваем наши сервисы с помощью .service или же .factory методы.
  4. $get это функция, которая напрямую связана с экземпляром провайдера Эта функция является заводской функцией. Другими словами, это так же, как тот, который мы используем для предоставления .factory метод. В этой функции мы создаем наш собственный сервис. это $get свойство, это функция, это то, что делает провайдера провайдером. AngularJS ожидает, что у провайдера будет свойство $ get, значением которого является функция, которую Angular будет рассматривать как фабричную функцию. Но что делает всю эту настройку провайдера особенной, так это то, что мы можем предоставить некоторые config объект внутри поставщика услуг, и это обычно идет со значениями по умолчанию, которые мы можем позже перезаписать на шаге, где мы можем настроить все приложение.

По сути, Поставщик, Завод и Сервис - все это Услуги. Фабрика - это особый случай службы, когда все, что вам нужно, это функция $get(), позволяющая писать ее с меньшим количеством кода.

Основные различия между Сервисами, Фабриками и Поставщиками заключаются в их сложности. Службы являются самой простой формой, фабрики немного более устойчивы, а провайдеры настраиваются во время выполнения.

Вот краткое изложение того, когда использовать каждый:

Фабрика: предоставляемое вами значение должно быть рассчитано на основе других данных.

Сервис: вы возвращаете объект с методами.

Поставщик: вы хотите иметь возможность настроить на этапе настройки объект, который будет создан до его создания. Используйте поставщика в основном в конфигурации приложения, прежде чем приложение будет полностью инициализировано.

Фабрика: фабрика, на которой вы фактически создаете объект внутри фабрики и возвращаете его.
service: служба, у вас просто есть стандартная функция, которая использует ключевое слово this для определения функции.
провайдер: в качестве провайдера вы определяете $get, и его можно использовать для получения объекта, который возвращает данные.

1.Услуги - это одноэлементные объекты, которые создаются при необходимости и никогда не очищаются до конца жизненного цикла приложения (когда браузер закрыт). Контроллеры уничтожаются и очищаются, когда они больше не нужны.

2. Самый простой способ создать сервис - использовать метод factory(). Метод factory() позволяет нам определять службу, возвращая объект, который содержит функции службы и данные службы. Функция определения сервиса - это место, где мы размещаем наши инъекционные сервисы, такие как $http и $q. Пример:

angular.module('myApp.services')
.factory('User', function($http) { // injectables go here
var backendUrl = "http://localhost:3000"; var service = {
    // our factory definition
user: {},
setName: function(newName) {
      service.user['name'] = newName;
    },
setEmail: function(newEmail) { service.user['email'] = newEmail;
},
save: function() {
return $http.post(backendUrl + '/users', { user: service.user
}); }
};
return service; });

Используя factory() в нашем приложении

В нашем приложении легко использовать фабрику, поскольку мы можем просто внедрить ее туда, где она нам нужна во время выполнения.

angular.module('myApp')
.controller('MainController', function($scope, User) {
  $scope.saveUser = User.save;
});
  1. Метод service(), с другой стороны, позволяет нам создавать сервис, определяя функцию конструктора. Мы можем использовать прототипный объект для определения нашего сервиса вместо необработанного объекта JavaScript. Подобно методу factory(), мы также установим инъецируемые элементы в определении функции.
  2. Самым низким способом создания сервиса является использование метода provide(). Это единственный способ создать службу, которую мы можем настроить с помощью функции.config(). В отличие от предыдущих методов, мы будем устанавливать инъецируемые объекты в определенном определении функции.$ Get().

Основываясь на целях памяти, контроллеры создаются только тогда, когда они необходимы, и отбрасываются, когда они не нужны. Из-за этого каждый раз, когда вы переключаете маршрут или перезагружаете страницу, Angular очищает текущий контроллер. Однако службы предоставляют средства для хранения данных в течение всего срока службы приложения, в то же время они также могут использоваться на разных контроллерах согласованным образом.

Angular предоставляет нам три способа создания и регистрации нашего собственного сервиса.

1) Фабрика

2) Сервис

3) Провайдер

Фабрика: Фабрика - это простая функция, которая позволяет вам добавить логику перед созданием объекта. Возвращает созданный объект.

Это просто набор функций, таких как класс. Следовательно, он может быть создан в разных контроллерах, когда вы используете его с функцией конструктора.

Сервис: Сервис - это функция конструктора, которая создает объект с использованием нового ключевого слова. Вы можете добавить свойства и функции к объекту службы, используя это ключевое слово. В отличие от завода, он ничего не возвращает.

Это одноэлементный объект. Используйте его, когда вам нужно совместно использовать один объект в приложении. Например, аутентифицированные данные пользователя.

Поставщик. Поставщик используется для создания настраиваемого объекта службы. Возвращает значение с помощью функции $get().

Когда вам нужно предоставить модульную конфигурацию для вашего сервисного объекта, прежде чем сделать его доступным.

Запустите следующий код и посмотрите вывод.

<!DOCTYPE html>
<html ng-app="app">
<head>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
    <meta charset=utf-8 />
    <title>JS Bin</title>
</head>
<body ng-controller="MyCtrl">
    {{serviceOutput}}
    <br/><br/>
    {{factoryOutput}}
    <br/><br/>
    {{providerOutput}}
    <script>
        var app = angular.module( 'app', [] );
        var MyFunc = function() {
            this.name = "default name";
            this.$get = function() {
                this.name = "new name"
                return "Hello from MyFunc.$get(). this.name = " + this.name;
            };
            return "Hello from MyFunc(). this.name = " + this.name;
        };
        // returns the actual function
        app.service( 'myService', MyFunc );
        // returns the function's return value
        app.factory( 'myFactory', MyFunc );
        // returns the output of the function's $get function
        app.provider( 'myProv', MyFunc );
        function MyCtrl( $scope, myService, myFactory, myProv ) {
            $scope.serviceOutput = "myService = " + myService;
            $scope.factoryOutput = "myFactory = " + myFactory;
            $scope.providerOutput = "myProvider = " + myProv;
        }
    </script>
</body>
</html>