Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: Service vs provider vs factory

What are the differences between a Service, Provider and Factory in AngularJS?

like image 813
Lior Avatar asked Mar 27 '13 17:03

Lior


People also ask

What is difference between factory service and provider in AngularJS?

The major difference between an AngularJS service and an AngularJS factory is that a service is a constructor function and a factory is not. That is why, in the case of a factory, we return an object literal instead of using this.

What is factory service in AngularJS?

What is Factory in AngularJS? Factory is an angular function which is used to return the values. A value on demand is created by the factory, whenever a service or controller needs it. Once the value is created, it is reused for all services and controllers. We can use the factory to create a service.

What is provider in AngularJS?

A provider is an object with a $get() method. The injector calls the $get method to create a new instance of a service. The Provider can have additional methods which would allow for configuration of the provider. AngularJS uses $provide to register new providers.

Is service and the provider are same?

A Service is a JavaScript object that exists in your application, and a Provider is the way you gain access to that object. The two are not the same thing, but they work together to make your Service accessible from other places. You can't get your Service without a Provider, and a Provider needs something to provide.


2 Answers

From the AngularJS mailing list I got an amazing thread that explains service vs factory vs provider and their injection usage. Compiling the answers:

Services

Syntax: module.service( 'serviceName', function );
Result: When declaring serviceName as an injectable argument you will be provided with an instance of the function. In other words new FunctionYouPassedToService().

Factories

Syntax: module.factory( 'factoryName', function );
Result: When declaring factoryName as an injectable argument you will be provided with the value that is returned by invoking the function reference passed to module.factory.

Providers

Syntax: module.provider( 'providerName', function );
Result: When declaring providerName as an injectable argument you will be provided with (new ProviderFunction()).$get(). The constructor function is instantiated before the $get method is called - ProviderFunction is the function reference passed to module.provider.

Providers have the advantage that they can be configured during the module configuration phase.

See here for the provided code.

Here's a great further explanation by Misko:

provide.value('a', 123);  function Controller(a) {   expect(a).toEqual(123); } 

In this case the injector simply returns the value as is. But what if you want to compute the value? Then use a factory

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

So factory is a function which is responsible for creating the value. Notice that the factory function can ask for other dependencies.

But what if you want to be more OO and have a class called Greeter?

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

Then to instantiate you would have to write

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

Then we could ask for 'greeter' in controller like this

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

But that is way too wordy. A shorter way to write this would be provider.service('greeter', Greeter);

But what if we wanted to configure the Greeter class before the injection? Then we could write

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);   }; }); 

Then we can do this:

angular.module('abc', []).config(function(greeter2Provider) {   greeter2Provider.setSalutation('Halo'); });  function Controller(greeter2) {   expect(greeter2.greet()).toEqual('Halo 123'); } 

As a side note, service, factory, and value are all derived from provider.

provider.service = function(name, Class) {   provider.provide(name, function() {     this.$get = function($injector) {       return $injector.instantiate(Class);     };   }); }  provider.factory = function(name, factory) {   provider.provide(name, function() {     this.$get = function($injector) {       return $injector.invoke(factory);     };   }); }  provider.value = function(name, value) {   provider.factory(name, function() {     return value;   }); }; 
like image 172
18 revs, 17 users 70% Avatar answered Sep 20 '22 12:09

18 revs, 17 users 70%


JS Fiddle Demo

" Hello world " example with 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>
like image 28
EpokK Avatar answered Sep 21 '22 12:09

EpokK