AngularJS Providers, Factories and Services

Angular Services

Angular relies heavily upon objects that it refers to as Services. An Angular Service is a singleton object that can be injected into other Angular components (other Services, Controllers, Directives, Filters, etc).

Services may be defined and registered in a number of ways using Angular’s Module interface. The Module interface offers the functions, provider, factory and service for service definition. (There are other service definition functions on this interface, but they’re of less interest here.) Each of these functions is used in a manner that the Angular documentation refers to as a recipe, with each offering varying degrees of sophistication and configurability.

The $provider Service can be used to register Services after Angular’s configuration phase, however we normally only require the Module interface.

Provider

Module.provider() offers the greatest flexibility in defining and registering a Service. Module.factory() and Module.service() wrap and simplify Module.provider() to achieve their results.

Here’s an example of a Pony Service defined and registered using Module.provider().

var Pony = function(ponyColour, FoodService) {
    // ...
};

var ponyModule = angular.module('ponyModule');

ponyModule.provider('Pony', function() {
    var colour = 'pink';

    this.setColour = function(value) {
        colour = value;
    };

    this.$get = ['Cheese', function(Cheese) {
        return new Pony(colour, Cheese);
    }];
};

After creating an Angular module named ponyModule, the above code defines and registers an Angular Service Provider which is used to create the Pony Service. The Service Provider is responsible for constructing and returning the Angular Service instance of Pony from its $get() factory function. Notice that the Pony service is also injected with the Cheese service (defined elsewhere).

The Provider method of creating a Service is overkill in most circumstances, but it is useful to understand Service creation in it’s more fundamental form. Only use this technique when a Service is used by more than one application and requires application-specific configuration during Angular’s module configuration phase.

In the above code, a pony’s colour may be overridden by calling the setColour() function (defined on the Provider object instance) during Angular’s configuration phase. Angular makes the Provider instance available to us by appending the word Provider to the Service name – PonyProvider in our case. The Provider instance can then be injected into the application’s configuration function:

var app = angular.module('app', ['Pony']);

app.config(['PonyProvider', function(PonyProvider) {
  PonyProvider.setColour('blue');
  // ...
});

Incidentally, the Provider instance itself can be injected with other Service Provider instances during Angular’s configuration phase, in much the same manner that dependency injection is performed on a Service.

Factory

Module.factory() offers the next most sophisticated way to define and register a Service. Using this technique, only the Provider’s $get() factory function is defined and registered:

ponyModule.factory('Pony', ['Cheese', function(Cheese) {
  return new Pony('blue', Cheese);
}]);

Here Service configurability (during Angular’s configuration phase) has been sacrifised in order to simplify Service registration.

Service

Module.service is the simplest technique for defining and registering a Service:

ponyModule.service('Pony', ['Cheese', function(Cheese) {
  this.colour: 'blue',
  // ...
}]);

Angular will call new on the Service constructor function for us. Slightly more configurability has been lost again, though the Service definition and registration is simpler. In the above use of Module.service() we have set a Pony‘s colour within the Module.service() function.

How flexible you require Service configuration will likely drive which of the above three techniques you employ. Module.service will likely be sufficient for defining and registering the Services used by most applications.