diff options
| author | Brian Ford | 2014-03-03 12:30:33 -0800 | 
|---|---|---|
| committer | Brian Ford | 2014-03-03 12:30:33 -0800 | 
| commit | 220e7bf2d448fd80d98d5c2f3cfac3902433df8f (patch) | |
| tree | 9b46c834e26a813705a6c39a418f7cef51f6e45b /docs/content/guide | |
| parent | 8d6eed21d219e459331a9f08fd46f8c67a9553da (diff) | |
| download | angular.js-220e7bf2d448fd80d98d5c2f3cfac3902433df8f.tar.bz2 | |
docs(guide/services): rewrite services documentation
Diffstat (limited to 'docs/content/guide')
| -rw-r--r-- | docs/content/guide/$location.ngdoc (renamed from docs/content/guide/dev_guide.services.$location.ngdoc) | 4 | ||||
| -rw-r--r-- | docs/content/guide/dev_guide.services.creating_services.ngdoc | 106 | ||||
| -rw-r--r-- | docs/content/guide/dev_guide.services.injecting_controllers.ngdoc | 123 | ||||
| -rw-r--r-- | docs/content/guide/dev_guide.services.managing_dependencies.ngdoc | 113 | ||||
| -rw-r--r-- | docs/content/guide/dev_guide.services.ngdoc | 20 | ||||
| -rw-r--r-- | docs/content/guide/dev_guide.services.testing_services.ngdoc | 62 | ||||
| -rw-r--r-- | docs/content/guide/dev_guide.services.understanding_services.ngdoc | 60 | ||||
| -rw-r--r-- | docs/content/guide/services.ngdoc | 297 | 
8 files changed, 299 insertions, 486 deletions
| diff --git a/docs/content/guide/dev_guide.services.$location.ngdoc b/docs/content/guide/$location.ngdoc index aae42ed2..a025aa47 100644 --- a/docs/content/guide/dev_guide.services.$location.ngdoc +++ b/docs/content/guide/$location.ngdoc @@ -1,5 +1,5 @@  @ngdoc overview -@name  Angular Services: Using $location +@name  Using $location  @description  # What does it do? @@ -329,7 +329,7 @@ reload to the original link.    Example: `<a href="http://angularjs.org/">link</a>`  - Links starting with '/' that lead to a different base path when base is defined<br>    Example: `<a href="/not-my-base/link">link</a>` -   +  When running Angular in the root of a domain, along side perhaps a normal application in the same  directory, the "otherwise" route handler will try to handle all the URLs, including ones that map  to static files. diff --git a/docs/content/guide/dev_guide.services.creating_services.ngdoc b/docs/content/guide/dev_guide.services.creating_services.ngdoc deleted file mode 100644 index d2d99157..00000000 --- a/docs/content/guide/dev_guide.services.creating_services.ngdoc +++ /dev/null @@ -1,106 +0,0 @@ -@ngdoc overview -@name  Angular Services: Creating Services -@description - -While Angular offers several useful services, for any nontrivial application you'll find it useful -to write your own custom services. To do this you begin by registering a service factory function -with a module either via the {@link angular.module Module#factory api} or directly -via the {@link auto.$provide $provide} api inside of module config function. - -All Angular services participate in {@link di dependency injection (DI)} by registering -themselves with Angular's DI system (injector) under a `name` (id) as well as by declaring -dependencies which need to be provided for the factory function of the registered service. The -ability to swap dependencies for mocks/stubs/dummies in tests allows for services to be highly -testable. - - -# Registering Services - -To register a service, you must have a module that this service will be part of. Afterwards, you -can register the service with the module either via the {@link angular.Module Module api} or -by using the {@link auto.$provide $provide} service in the module configuration -function. The following pseudo-code shows both approaches: - -Using the angular.Module api: - -```js -var myModule = angular.module('myModule', []); -myModule.factory('serviceId', function() { -  var shinyNewServiceInstance; -  //factory function body that constructs shinyNewServiceInstance -  return shinyNewServiceInstance; -}); -``` - -Using the $provide service: - -```js -angular.module('myModule', [], function($provide) { -  $provide.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 not only be depended upon, but can also have their own dependencies. These can be specified -as arguments of the factory function. {@link di Read more} about dependency injection (DI) -in Angular and the use of array notation and the $inject property to make DI annotation -minification-proof. - -Following is an example of a very simple service. This service depends on the `$window` service -(which is passed as a parameter to the factory function) and is just a function. The service simply -stores all notifications; after the third one, the service displays all of the notifications by -window alert. - -```js -angular.module('myModule', [], function($provide) { -  $provide.factory('notify', ['$window', function(win) { -    var msgs = []; -    return function(msg) { -      msgs.push(msg); -      if (msgs.length == 3) { -        win.alert(msgs.join("\n")); -        msgs = []; -      } -    }; -  }]); -}); -``` - - -# Instantiating Angular Services - -All services in Angular are instantiated lazily. This means that a service will be created -only when it is needed for instantiation of a service or an application component that depends on it. -In other words, Angular won't instantiate services unless they are requested directly or -indirectly by the application. - - -# Services as singletons - -Lastly, it is important to realize that all Angular services are application singletons. This means -that there is only one instance of a given service per injector. Since Angular is lethally allergic -to global state, it is possible to create multiple injectors, each with its own instance of a -given service, but that is rarely needed, except in tests where this property is crucially -important. - - - -## Related Topics - -* {@link dev_guide.services.understanding_services Understanding Angular Services} -* {@link dev_guide.services.managing_dependencies Managing Service Dependencies} -* {@link dev_guide.services.injecting_controllers Injecting Services Into Controllers } -* {@link dev_guide.services.testing_services Testing Angular Services} - -## Related API - -* {@link ng Angular Service API} diff --git a/docs/content/guide/dev_guide.services.injecting_controllers.ngdoc b/docs/content/guide/dev_guide.services.injecting_controllers.ngdoc deleted file mode 100644 index ac58b4e4..00000000 --- a/docs/content/guide/dev_guide.services.injecting_controllers.ngdoc +++ /dev/null @@ -1,123 +0,0 @@ -@ngdoc overview -@name  Angular Services: Injecting Services Into Controllers -@description - -Using services as dependencies for controllers is very similar to using services as dependencies -for another service. - -Since JavaScript is a dynamic language, DI can't figure out which services to inject by static -types (like in static typed languages). Therefore, you can specify the service name by using the -`$inject` property, which is an array containing strings with names of services to be injected. -The name must match the corresponding service ID registered with angular. The order of the service -IDs matters: the order of the services in the array will be used when calling the factory function -with injected parameters. The names of parameters in factory function don't matter, but by -convention they match the service IDs, which has added benefits discussed below. - -```js -function myController($loc, $log) { -  this.firstMethod = function() { -    // use $location service -    $loc.setHash(); -  }; -  this.secondMethod = function() { -    // use $log service -    $log.info('...'); -  }; -} -// which services to inject ? -myController.$inject = ['$location', '$log']; -``` - -<example module="MyServiceModule"> -  <file name="index.html"> -    <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> -  </file> - -  <file name="script.js"> -    angular. -     module('MyServiceModule', []). -     factory('notify', ['$window', function(win) { -        var msgs = []; -        return function(msg) { -          msgs.push(msg); -          if (msgs.length == 3) { -            win.alert(msgs.join("\n")); -            msgs = []; -          } -        }; -      }]); - -    function myController(scope, notifyService) { -      scope.callNotify = function(msg) { -        notifyService(msg); -      }; -    } - -    myController.$inject = ['$scope','notify']; -  </file> - -  <file name="protractor.js" type="protractor"> -    it('should test service', function() { -      expect(element(by.id('simple')).element(by.model('message')).getAttribute('value')) -          .toEqual('test'); -    }); -  </file> -</example> - -## Implicit Dependency Injection - -A new feature of Angular DI allows it to 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: - -<example module="MyServiceModuleDI"> -  <file name="index.html"> -    <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> -  </file> - -  <file name="script.js"> -    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 = []; -          } -        }; -      }); - -    function myController($scope, notify) { -      $scope.callNotify = function(msg) { -        notify(msg); -      }; -    } -  </file> -</example> - -However, if you plan to [minify](http://en.wikipedia.org/wiki/Minification_(programming)) your -code, your variable names will get renamed in which case you will still need to explicitly specify -dependencies with the `$inject` property. - -## Related Topics - -* {@link dev_guide.services.understanding_services Understanding Angular Services} -* {@link dev_guide.services.creating_services Creating Angular Services} -* {@link dev_guide.services.managing_dependencies Managing Service Dependencies} -* {@link dev_guide.services.testing_services Testing Angular Services} - -## Related APIs - -* {@link ng Angular Service API} diff --git a/docs/content/guide/dev_guide.services.managing_dependencies.ngdoc b/docs/content/guide/dev_guide.services.managing_dependencies.ngdoc deleted file mode 100644 index e9d8be8c..00000000 --- a/docs/content/guide/dev_guide.services.managing_dependencies.ngdoc +++ /dev/null @@ -1,113 +0,0 @@ -@ngdoc overview -@name  Angular Services: Managing Service Dependencies -@description - -Angular allows services to declare other services as dependencies needed for construction of their -instances. - -To declare dependencies, you specify them in the factory function signature and annotate the -function with the inject annotations either using by setting the `$inject` property, as an array of -string identifiers or using the array notation. Optionally the `$inject` property declaration can be -dropped (see "Inferring `$inject`" but note that that is currently an experimental feature). - -Using the array notation: - -```js -function myModuleCfgFn($provide) { -  $provide.factory('myService', ['dep1', 'dep2', function(dep1, dep2) {}]); -} -``` - - -Using the $inject property: - -```js -function myModuleCfgFn($provide) { -  var myServiceFactory = function(dep1, dep2) {}; -  myServiceFactory.$inject = ['dep1', 'dep2']; -  $provide.factory('myService', myServiceFactory); -} -``` - - -Using DI inference (incompatible with minifiers): - -```js -function myModuleCfgFn($provide) { -  $provide.factory('myService', function(dep1, dep2) {}); -} -``` - - -Here is an example of two services, one of which depends on the other and both -of which depend on other services that are provided by the Angular framework: - -```js -/** - * 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. - */ -  function batchLogModule($provide){ -    $provide.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. -     */ -    $provide.factory('routeTemplateMonitor', -                ['$route', 'batchLog', '$rootScope', -         function($route,   batchLog,   $rootScope) { -      $rootScope.$on('$routeChangeSuccess', function() { -        batchLog($route.current ? $route.current.template : null); -      }); -    }]); -  } - -  // get the main service to kick off the application -  angular.injector([batchLogModule]).get('routeTemplateMonitor'); -``` - -Things to notice in this example: - -* The `batchLog` service depends on the built-in {@link ng.$interval $interval} and -{@link ng.$log $log} services, and allows messages to be logged into the -`console.log` in batches. -* The `routeTemplateMonitor` service depends on the built-in {@link ngRoute.$route -$route} service as well as our custom `batchLog` service. -* Both of our services use the factory function signature and array notation for inject annotations -to declare their dependencies. It is important that the order of the string identifiers in the array -is the same as the order of argument names in the signature of the factory function. Unless the -dependencies are inferred from the function signature, it is this array with IDs and their order -that the injector uses to determine which services and in which order to inject. - - -## Related Topics - -* {@link dev_guide.services.understanding_services Understanding Angular Services} -* {@link dev_guide.services.creating_services Creating Angular Services} -* {@link dev_guide.services.injecting_controllers Injecting Services Into Controllers } -* {@link dev_guide.services.testing_services Testing Angular Services} - - -## Related API - -* {@link ./ng Angular Service API} -* {@link angular.injector Angular Injector API} diff --git a/docs/content/guide/dev_guide.services.ngdoc b/docs/content/guide/dev_guide.services.ngdoc deleted file mode 100644 index 29eba46f..00000000 --- a/docs/content/guide/dev_guide.services.ngdoc +++ /dev/null @@ -1,20 +0,0 @@ -@ngdoc overview -@name  Angular Services -@description - -Services are a feature that Angular brings to client-side web apps from the server side, where -services have been commonly used for a long time. Services in Angular apps are substitutable -objects that are wired together using {@link di dependency injection (DI)}. - - -## Related Topics - -* {@link dev_guide.services.understanding_services Understanding Angular Services} -* {@link dev_guide.services.creating_services Creating Angular Services} -* {@link dev_guide.services.managing_dependencies Managing Service Dependencies} -* {@link dev_guide.services.injecting_controllers Injecting Services Into Controllers} -* {@link dev_guide.services.testing_services Testing Angular Services} - -## Related API - -* {@link ./ng Angular Service API} diff --git a/docs/content/guide/dev_guide.services.testing_services.ngdoc b/docs/content/guide/dev_guide.services.testing_services.ngdoc deleted file mode 100644 index 67a1635d..00000000 --- a/docs/content/guide/dev_guide.services.testing_services.ngdoc +++ /dev/null @@ -1,62 +0,0 @@ -@ngdoc overview -@name  Angular Services: Testing Angular Services -@description - -The following is a unit test for the 'notify' service in the 'Dependencies' example in {@link -dev_guide.services.creating_services Creating Angular Services}. The unit test example uses Jasmine -spy (mock) instead of a real browser alert. - -```js -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"]); -}); -``` - - -## Related Topics - -* {@link dev_guide.services.understanding_services Understanding Angular Services} -* {@link dev_guide.services.creating_services Creating Angular Services} -* {@link dev_guide.services.managing_dependencies Managing Service Dependencies} -* {@link dev_guide.services.injecting_controllers Injecting Services Into Controllers} - -## Related API - -* {@link ./ng Angular Service API} diff --git a/docs/content/guide/dev_guide.services.understanding_services.ngdoc b/docs/content/guide/dev_guide.services.understanding_services.ngdoc deleted file mode 100644 index b1750884..00000000 --- a/docs/content/guide/dev_guide.services.understanding_services.ngdoc +++ /dev/null @@ -1,60 +0,0 @@ -@ngdoc overview -@name  Angular Services: Understanding Angular Services -@description - -## What are Angular Services? - -Angular services are singletons objects or functions that carry out specific tasks common to web apps. -Angular has a number of built in services, such as the {@link ng.$http $http service}, which -provides access to the browser's `XMLHttpRequest` object for making requests to a server. Like other core -Angular variables and identifiers, the built-in services always start with `$` (such as `$http` mentioned -above). You can also create your own custom services. - -## Using a Service - -To use an Angular service, you identify 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. The Angular injector subsystem is in charge of service instantiation, resolution -of dependencies, and provision of dependencies to components as requested. - -Angular injects dependencies using -["constructor" injection](http://misko.hevery.com/2009/02/19/constructor-injection-vs-setter-injection/). -The dependency is passed to the component's factory/constructor function. Because JavaScript is a dynamically -typed language, Angular's dependency injection subsystem cannot use static types to identify service -dependencies. For this reason a component must, explicitly, define its dependencies by using one of the -{@link di injection annotation} methods.  For example, by providing a `$inject` property: - -        var MyController = function($location) { ... }; -        MyController.$inject = ['$location']; -        myModule.controller('MyController', MyController); - -Or by providing an "inline" injection annotation: - -        var myService = function($http) { ... }; -        myModule.factory('myService', ['$http', myService]); - -## Defining a Service - -Application developers are free to define their own services by registering their name, and **service -factory function**, in Angular modules. - -The purpose of the **service factory function** is to generate the single object, or function, that  -represents the service to the rest of the application. That object, or function, will then be -injected into any component (controller, service, filter or directive) that specifies a dependency -on the service. - -Angular factory functions are executed lazily. That is, they are only executed when needed  -to satisfy a dependency, and are then executed exactly once for each service. Everything that is -dependent on this service gets a reference to the single instance generated by the service factory. - -## Related Topics - -* {@link guide/di About Angular Dependency Injection} -* {@link guide/dev_guide.services.creating_services Creating Angular Services} -* {@link guide/dev_guide.services.managing_dependencies Managing Service Dependencies} -* {@link guide/dev_guide.services.testing_services Testing Angular Services} - -## Related API - -* {@link ./ng Angular Service API} -* {@link angular.injector Injector API} diff --git a/docs/content/guide/services.ngdoc b/docs/content/guide/services.ngdoc new file mode 100644 index 00000000..d92be142 --- /dev/null +++ b/docs/content/guide/services.ngdoc @@ -0,0 +1,297 @@ +@ngdoc overview +@name  Services +@description + +# Services + +Angular services are substitutable objects that are wired together using {@link di dependency +injection (DI)}. You can use services to organize and share code across your app. + +Angular services are: + +* Lazily instantiated – Angular only instantiates a service when an application component depends +  on it. +* Singletons – Each component is dependent on a service gets a reference to the single instance +  generated by the service factory. + +Angular offers several useful services (like {@link ng.$http `$http`}) but for most applications +you'll also want to {@link services#creating-services create your own}. + +<div class="alert alert-info"> +**Note:** Like other core Angular identifiers built-in services always start with `$` +(i.e. `$http`). +</div> + + +## 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 {@link di dependency injection} +subsystem takes care of the rest. + +<example module="myServiceModule"> +  <file name="index.html"> +    <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> +  </file> + +  <file name="script.js"> +    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 = []; +          } +        }; +      }]); +  </file> + +  <file name="protractor.js" type="protractor"> +    it('should test service', function() { +      expect(element(by.id('simple')).element(by.model('message')).getAttribute('value')) +          .toEqual('test'); +    }); +  </file> +</example> + +<div class="alert alert-info"> +**Note:** Angular uses +[**constructor injection**](http://misko.hevery.com/2009/02/19/constructor-injection-vs-setter-injection/). +</div> + +### Explicit Dependency Injection + +A component should explicitly define its dependencies using one of the {@link di injection +annotation} methods: + +1. Inline array injection annotation (preferred): +  ```js +  myModule.controller('MyController', ['$location', function($location) { ... }]); +  ``` + +2. `$inject` property: +  ```js +  var MyController = function($location) { ... }; +  MyController.$inject = ['$location']; +  myModule.controller('MyController', MyController); +  ``` + +<div class="alert alert-success"> +**Best Practice:** Use the array annotation shown above. +</div> + +### 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: + +<example module="myServiceModuleDI"> +  <file name="index.html"> +    <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> +  </file> + +  <file name="script.js"> +    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); +        }; +      }); +  </file> +</example> + +<div class="alert alert-error"> +**Careful:** If you plan to [minify](http://en.wikipedia.org/wiki/Minification_(programming) your code, +your variable names will get renamed unless you use one of the annotation techniques above. +</div> + + +## 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 {@link angular.Module Module API}. +Typically you use the {@link angular.module Module#factory} API to register a service: + +```javascript +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: + +```js +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: + +* The `batchLog` service depends on the built-in {@link ng.$interval `$interval`} and +  {@link ng.$log `$log`} services. +* The `routeTemplateMonitor` service depends on the built-in {@link ngRoute.$route `$route`} +  service and our custom `batchLog` service. +* Both services use the and array notation to declare their dependencies. +* That the order of identifiers in the array is the same as the order of argument +  names in the factory function. + +### Registering a Service with `$provide` + +You can also register services via the {@link auto.$provide `$provide`} service inside of a +module's `config` function: + +```javascript +angular.module('myModule', []).config(function($provide) { +  $provide.factory('serviceId', function() { +    var shinyNewServiceInstance; +    //factory function body that constructs shinyNewServiceInstance +    return shinyNewServiceInstance; +  }); +}); +``` + +This is 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 {@link services#creating-services +Creating Angular Services} example above. The unit test example uses a Jasmine spy (mock) instead +of a real browser alert. + +```js +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"]); +}); +``` + + +## Related Topics + +* {@link guide/di Dependency Injection in AngularJS} + +## Related API + +* {@link ./ng Angular Service API} +* {@link angular.injector Injector API} | 
