Improve this doc

Services

Angular services are substitutable objects that are wired together using dependency injection (DI). You can use services to organize and share code across your app.

Angular services are:

Angular offers several useful services (like $http), but for most applications you'll also want to create your own.

Note: Like other core Angular identifiers built-in services always start with $ (e.g. $http).

Using a Service

To use an Angular service, you add it as a dependency for the component (controller, service, filter or directive) that depends on the service. Angular's dependency injection subsystem takes care of the rest.

  Edit in Plunker
<div id="simple" ng-controller="MyController">
  <p>Let's try this simple notify service, injected into the controller...</p>
  <input ng-init="message='test'" ng-model="message" >
  <button ng-click="callNotify(message);">NOTIFY</button>
  <p>(you have to click 3 times to see an alert)</p>
</div>
angular.
 module('myServiceModule', []).
  controller('MyController', ['$scope','notify', function ($scope, notify) {
    $scope.callNotify = function(msg) {
      notify(msg);
    };
  }]).
 factory('notify', ['$window', function(win) {
    var msgs = [];
    return function(msg) {
      msgs.push(msg);
      if (msgs.length == 3) {
        win.alert(msgs.join("\n"));
        msgs = [];
      }
    };
  }]);
it('should test service', function() {
  expect(element(by.id('simple')).element(by.model('message')).getAttribute('value'))
      .toEqual('test');
});

Note: Angular uses constructor injection.

Explicit Dependency Injection

A component should explicitly define its dependencies using one of the injection annotation methods:

  1. Inline array injection annotation (preferred):

    myModule.controller('MyController', ['$location', function($location) { ... }]);
  2. $inject property:

    var MyController = function($location) { ... };
    MyController.$inject = ['$location'];
    myModule.controller('MyController', MyController);
Best Practice: Use the array annotation shown above.

Implicit Dependency Injection

Even if you don't annotate your dependencies, Angular's DI can determine the dependency from the name of the parameter. Let's rewrite the above example to show the use of this implicit dependency injection of $window, $scope, and our notify service:

  Edit in Plunker
<div id="implicit" ng-controller="MyController">
  <p>Let's try the notify service, that is implicitly injected into the controller...</p>
  <input ng-init="message='test'" ng-model="message">
  <button ng-click="callNotify(message);">NOTIFY</button>
  <p>(you have to click 3 times to see an alert)</p>
</div>
angular.module('myServiceModuleDI', []).
  factory('notify', function($window) {
    var msgs = [];
    return function(msg) {
      msgs.push(msg);
      if (msgs.length == 3) {
        $window.alert(msgs.join("\n"));
        msgs = [];
      }
    };
  }).
  controller('MyController', function($scope, notify) {
    $scope.callNotify = function(msg) {
      notify(msg);
    };
  });

Careful: If you plan to minify your code, your variable names will get renamed unless you use one of the annotation techniques above.
If you use a tool like ngmin in your workflow you can use implicit dependency notation within your codebase and let ngmin automatically convert such injectable functions to the array notation prior to minifying.

Creating Services

Application developers are free to define their own services by registering the service's name and service factory function, with an Angular module.

The service factory function generates the single object or function that represents the service to the rest of the application. The object or function returned by the service is injected into any component (controller, service, filter or directive) that specifies a dependency on the service.

Registering Services

Services are registered to modules via the Module API. Typically you use the Module#factory API to register a service:

var myModule = angular.module('myModule', []);
myModule.factory('serviceId', function() {
  var shinyNewServiceInstance;
  //factory function body that constructs shinyNewServiceInstance
  return shinyNewServiceInstance;
});

Note that you are not registering a service instance, but rather a factory function that will create this instance when called.

Dependencies

Services can have their own dependencies. Just like declaring dependencies in a controller, you declare dependencies by specifying them in the service's factory function signature.

The example module below has two services, each with various dependencies:

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

/**
 * The `batchLog` service allows for messages to be queued in memory and flushed
 * to the console.log every 50 seconds.
 *
 * @param {*} message Message to be logged.
 */
batchModule.factory('batchLog', ['$interval', '$log', function($interval, $log) {
  var messageQueue = [];

  function log() {
    if (messageQueue.length) {
      $log.log('batchLog messages: ', messageQueue);
      messageQueue = [];
    }
  }

  // start periodic checking
  $interval(log, 50000);

  return function(message) {
    messageQueue.push(message);
  }
}]);

/**
 * `routeTemplateMonitor` monitors each `$route` change and logs the current
 * template via the `batchLog` service.
 */
batchModule.factory('routeTemplateMonitor', ['$route', 'batchLog', '$rootScope',
  function($route, batchLog, $rootScope) {
    $rootScope.$on('$routeChangeSuccess', function() {
      batchLog($route.current ? $route.current.template : null);
    });
  }]);

In the example, note that:

Registering a Service with $provide

You can also register services via the $provide service inside of a module's config function:

angular.module('myModule', []).config(function($provide) {
  $provide.factory('serviceId', function() {
    var shinyNewServiceInstance;
    //factory function body that constructs shinyNewServiceInstance
    return shinyNewServiceInstance;
  });
});

This technique is often used in unit tests to mock out a service's dependencies.

Unit Testing

The following is a unit test for the notify service from the Creating Angular Services example above. The unit test example uses a Jasmine spy (mock) instead of a real browser alert.

var mock, notify;

beforeEach(function() {
  mock = {alert: jasmine.createSpy()};

  module(function($provide) {
    $provide.value('$window', mock);
  });

  inject(function($injector) {
    notify = $injector.get('notify');
  });
});

it('should not alert first two notifications', function() {
  notify('one');
  notify('two');

  expect(mock.alert).not.toHaveBeenCalled();
});

it('should alert all after third notification', function() {
  notify('one');
  notify('two');
  notify('three');

  expect(mock.alert).toHaveBeenCalledWith("one\ntwo\nthree");
});

it('should clear messages after alert', function() {
  notify('one');
  notify('two');
  notify('third');
  notify('more');
  notify('two');
  notify('third');

  expect(mock.alert.callCount).toEqual(2);
  expect(mock.alert.mostRecentCall.args).toEqual(["more\ntwo\nthird"]);
});