About services, factories, and providers in AngularJS

angular_di.png

AngularJS module objects have five functions that declare services to the dependency injector. The three most common ways are the service(), factory(), and provider() functions.

The factory() Function

The factory() function is the simplest and most common way to create a service in AngularJS. Fundamentally, a factory is a function that the dependency injector uses to create an instance of the service. Syntactically, a factory looks like this

app.factory('myService', function() {
    var myService = {};
    // define myService
    return myService;
});

The return value of the given function is injected into any function that lists myService as a dependency. For example:

app.factory('myService', function() {
    var myService = {
        foo: "bar"
    };
    return myService;
});

app.controller('MyCtrl', function(myService) {
    console.log(myService.foo);
});

A factory can take parameters through dependency injection, so you can reuse services like $http (or even your own custom services) in your services.

Services are always singletons in the sense that there is one instance of the service that’s shared between all controllers and services that use it.

The service() Function

The redundantly named service() function is another convenient way of creating a service. As you’ll see, the service() function offers essentially the same functionality as the factory() function, with a few academic differences.

The difference between the service() function and the factory() function is that, whereas the factory() function requires you to construct an object in your code and return it, the function you pass to the service() function is executed using JavaScript’s new operator. In other words, when using the service() function, you don’t have to explicitly construct and return a new object; you simply need to attach properties to this. Here’s how using the service() function looks in real JavaScript

app.service('myService', function() {
    this.foo = "bar";
});
app.controller('MyCtrl', function(myService) {
    console.log(myService.foo);
});

The service() function is often more succinct. However, the this keyword is confusing and difficult to use properly in JavaScript, and many developers avoid using it out of principle. functions.

The factory() and service() functions create services the same way every time, but providers effectively enable you to switch which factory function the dependency injector uses to construct a given function.

The provider() Function

The provider() function is the most expressive way to create services, and, correspondingly, the most complex. At a high level, the provider() function lets you determine which service to register based on application-wide configuration. As a matter of fact, under the hood, the factory() and service() functions you just learned about are implemented as syntactic sugar on top of the provider() function. For most cases, the provider() function is overkill, and you often build out an entire AngularJS app without creating a single provider.

The primary purpose of the config() function is to configure the application’s providers so the application uses the correct services. The contents of a config() function are typically called a configuration block. AngularJS runs your configuration blocks in order before any controllers, services, or directives are instantiated.

Syntactically, a configuration block looks like this:

app.config(function($httpProvider) {
    // use $httpProvider here
});

Note that configuration blocks are the only place where you can access providers through dependency injection rather than the services themselves.

comments powered by Disqus