From 770353df1956ab45bdbe45a4d5040caa40bf880f Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Thu, 10 Oct 2013 16:46:59 +0100 Subject: docs($provide): improve docs and examples further Improve the "tracking" service example by adding a configuration option. Get better formatting of the generated code samples using
 tags.
Move the detailed explanations into each function's documentation block.
Improve the overview and list the constituent functions by significance.

Closes #4302
---
 src/auto/injector.js | 293 +++++++++++++++++++++++++++++++++++----------------
 1 file changed, 204 insertions(+), 89 deletions(-)

diff --git a/src/auto/injector.js b/src/auto/injector.js
index b93446c0..8f8b78cf 100644
--- a/src/auto/injector.js
+++ b/src/auto/injector.js
@@ -253,83 +253,37 @@ function annotate(fn) {
  *
  * @description
  *
- * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.
- * The providers share the same name as the instance they create with `Provider` suffixed to them.
- *
- * 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.
- *
- * 
- *   function TrackingProvider() {
- *     this.$get = function($http) {
- *       var observed = {};
- *       return {
- *         event: function(event) {
- *           var current = observed[event];
- *           return observed[event] = current ? current + 1 : 1;
- *         },
- *         save: function() {
- *           $http.post("/track",observed);
- *         }
- *       };
- *     };
- *   }
- *
- *   describe('Tracking', function() {
- *     var mocked;
- *     beforeEach(module(function($provide) {
- *       $provide.provider('tracking', TrackingProvider);
- *       mocked = {post: jasmine.createSpy('postSpy')};
- *       $provide.value('$http',mocked);
- *     }));
- *     it('allows events to be tracked', inject(function(tracking) {
- *       expect(tracking.event('login')).toEqual(1);
- *       expect(tracking.event('login')).toEqual(2);
- *     }));
- *
- *     it('posts to save', inject(function(tracking) {
- *       tracking.save();
- *       expect(mocked.post.callCount).toEqual(1);
- *     }));
- *   });
- * 
- * - * There are also shorthand methods to define services that don't need to be configured beyond their `$get()` method. - * - * `service()` registers a constructor function which will be invoked with `new` to create the instance. You can specify services that will be provided by the injector. - * - *
- *    function TrackingProvider($http) {
- *      var observed = {};
- *      this.event = function(event) {
- *        var current = observed[event];
- *        return observed[event] = current ? current + 1 : 1;
- *      };
- *      this.save = function() {
- *        $http.post("/track",observed);
- *      };
- *    }
- *    $provider.service('tracking',TrackingProvider);
- *  
- * - * `factory()` registers a function whose return value is the instance. Again, you can specify services that will be provided by the injector. - * - *
- *    function TrackingProvider($http) {
- *      var observed = {};
- *      return {
- *        event: function(event) {
- *          var current = observed[event];
- *          return observed[event] = current ? current + 1 : 1;
- *        },
- *        save: function() {
- *          $http.post("/track",observed);
- *        }
- *      };
- *    }
- *    $provider.factory('tracking',TrackingProvider);
- *  
- * + * The {@link AUTO.$provide $provide} service has a number of methods for registering components with + * the {@link AUTO.$injector $injector}. Many of these functions are also exposed on {@link angular.Module}. + * + * An Angular **service** is a singleton object created by a **service factory**. These **service + * factories** are functions which, in turn, are created by a **service provider**. + * The **service providers** are constructor functions. When instantiated they must contain a property + * called `$get`, which holds the **service factory** function. + * + * When you request a service, the {@link AUTO.$injector $injector} is responsible for finding the + * correct **service provider**, instantiating it and then calling its `$get` **service factory** + * function to get the instance of the **service**. + * + * Often services have no configuration options and there is no need to add methods to the service + * provider. The provider will be no more than a constructor function with a `$get` property. For + * these cases the {@link AUTO.$provide $provide} service has additional helper methods to register + * services without specifying a provider. + * + * * {@link AUTO.$provide#provider provider(provider)} - registers a **service provider** with the + * {@link AUTO.$injector $injector} + * * {@link AUTO.$provide#constant constant(obj)} - registers a value/object that can be accessed by + * providers and services. + * * {@link AUTO.$provide#value value(obj)} - registers a value/object that can only be accessed by + * services, not providers. + * * {@link AUTO.$provide#factory factory(fn)} - registers a service **factory function**, `fn`, that + * will be wrapped in a **service provider** object, whose `$get` property will contain the given + * factory function. + * * {@link AUTO.$provide#service service(class)} - registers a **constructor function**, `class` that + * will be wrapped in a **service provider** object, whose `$get` property will instantiate a new + * object using the given constructor function. + * + * See the individual methods for more information and examples. */ /** @@ -338,7 +292,18 @@ function annotate(fn) { * @methodOf AUTO.$provide * @description * - * Register a provider for a service. The providers can be retrieved and can have additional configuration methods. + * Register a **provider function** with the {@link AUTO.$injector $injector}. Provider functions are + * constructor functions, whose instances are responsible for "providing" a factory for a service. + * + * Service provider names start with the name of the service they provide followed by `Provider`. + * For example, the {@link ng.$log $log} service has a provider called {@link ng.$logProvider $logProvider}. + * + * Service provider objects can have additional methods which allow configuration of the provider and + * its service. Importantly, you can configure what kind of service is created by the `$get` method, + * or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a method + * {@link ng.$logProvider#debugEnabled debugEnabled} + * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the + * console or not. * * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key. * @param {(Object|function())} provider If the provider is: @@ -349,6 +314,70 @@ function annotate(fn) { * {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`. * * @returns {Object} registered provider instance + + * @example + * + * The following example shows how to create a simple event tracking service and register it using + * {@link AUTO.$provide#provider $provide.provider()}. + * + *
+ *  // Define the eventTracker provider
+ *  function EventTrackerProvider() {
+ *    var trackingUrl = '/track';
+ *
+ *    // A provider method for configuring where the tracked events should been saved
+ *    this.setTrackingUrl = function(url) {
+ *      trackingUrl = url;
+ *    };
+ *
+ *    // The service factory function
+ *    this.$get = ['$http', function($http) {
+ *      var trackedEvents = {};
+ *      return {
+ *        // Call this to track an event
+ *        event: function(event) {
+ *          var count = trackedEvents[event] || 0;
+ *          count += 1;
+ *          trackedEvents[event] = count;
+ *          return count;
+ *        },
+ *        // Call this to save the tracked events to the trackingUrl
+ *        save: function() {
+ *          $http.post(trackingUrl, trackedEvents);
+ *        }
+ *      };
+ *    }];
+ *  }
+ *
+ *  describe('eventTracker', function() {
+ *    var postSpy;
+ *
+ *    beforeEach(module(function($provide) {
+ *      // Register the eventTracker provider
+ *      $provide.provider('eventTracker', EventTrackerProvider);
+ *    }));
+ *
+ *    beforeEach(module(function(eventTrackerProvider) {
+ *      // Configure eventTracker provider
+ *      eventTrackerProvider.setTrackingUrl('/custom-track');
+ *    }));
+ *
+ *    it('tracks events', inject(function(eventTracker) {
+ *      expect(eventTracker.event('login')).toEqual(1);
+ *      expect(eventTracker.event('login')).toEqual(2);
+ *    }));
+ *
+ *    it('saves to the tracking url', inject(function(eventTracker, $http) {
+ *      postSpy = spyOn($http, 'post');
+ *      eventTracker.event('login');
+ *      eventTracker.save();
+ *      expect(postSpy).toHaveBeenCalled();
+ *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
+ *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
+ *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
+ *    }));
+ *  });
+ * 
*/ /** @@ -357,12 +386,32 @@ function annotate(fn) { * @methodOf AUTO.$provide * @description * - * A service whose instance is the return value of `$getFn`. Short hand for configuring services if only `$get` method is required. + * Register a **service factory**, which will be called to return the service instance. + * This is short for registering a service where its provider consists of only a `$get` property, + * which is the given service factory function. + * You should use {@link AUTO.$provide#factory $provide.factor(getFn)} if you do not need to configure + * your service in a provider. * * @param {string} name The name of the instance. * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for * `$provide.provider(name, {$get: $getFn})`. * @returns {Object} registered provider instance + * + * @example + * Here is an example of registering a service + *
+ *   $provide.factory('ping', ['$http', function($http) {
+ *     return function ping() {
+ *       return $http.send('/ping');
+ *     };
+ *   }]);
+ * 
+ * You would then inject and use this service like this: + *
+ *   someModule.controller('Ctrl', ['ping', function(ping) {
+ *     ping();
+ *   }]);
+ * 
*/ @@ -372,11 +421,34 @@ function annotate(fn) { * @methodOf AUTO.$provide * @description * - * A service whose instance is created by invoking `constructor` with `new`. A short hand for registering services which use a constructor. + * Register a **service constructor**, which will be invoked with `new` to create the service instance. + * This is short for registering a service where its provider's `$get` property is the service + * constructor function that will be used to instantiate the service instance. + * + * You should use {@link AUTO.$provide#service $provide.service(class)} if you define your service + * as a type/class. This is common when using {@link http://coffeescript.org CoffeeScript}. * * @param {string} name The name of the instance. * @param {Function} constructor A class (constructor function) that will be instantiated. * @returns {Object} registered provider instance + * + * @example + * Here is an example of registering a service using {@link AUTO.$provide#service $provide.service(class)} + * that is defined as a CoffeeScript class. + *
+ *   class Ping
+ *     constructor: (@$http)->
+ *     send: ()=>
+ *       @$http.get('/ping')
+ *  
+ *   $provide.service('ping', ['$http', Ping])
+ * 
+ * You would then inject and use this service like this: + *
+ *   someModule.controller 'Ctrl', ['ping', (ping)->
+ *     ping.send()
+ *   ]
+ * 
*/ @@ -386,11 +458,29 @@ function annotate(fn) { * @methodOf AUTO.$provide * @description * - * A short hand for configuring services if the `$get` method is a constant. + * Register a **value service** with the {@link AUTO.$injector $injector}, such as a string, a number, + * an array, an object or a function. This is short for registering a service where its provider's + * `$get` property is a factory function that takes no arguments and returns the **value service**. * + * Value services are similar to constant services, except that they cannot be injected into a module + * configuration function (see {@link angular.Module#config}) but they can be overridden by an Angular + * {@link AUTO.$provide#decorator decorator}. + * * @param {string} name The name of the instance. * @param {*} value The value. * @returns {Object} registered provider instance + * + * @example + * Here are some examples of creating value services. + *
+ *   $provide.constant('ADMIN_USER', 'admin');
+ *   
+ *   $provide.constant('RoleLookup', { admin: 0, writer: 1, reader: 2 });
+ *   
+ *   $provide.constant('halfOf', function(value) {
+ *     return value / 2;
+ *   });
+ * 
*/ @@ -400,13 +490,26 @@ function annotate(fn) { * @methodOf AUTO.$provide * @description * - * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected - * into configuration function (other modules) and it is not interceptable by - * {@link AUTO.$provide#decorator decorator}. + * Register a **constant service**, such as a string, a number, an array, an object or a function, with + * the {@link AUTO.$injector $injector}. Unlike {@link AUTO.$provide#value value} it can be injected + * into a module configuration function (see {@link angular.Module#config}) and it cannot be + * overridden by an Angular {@link AUTO.$provide#decorator decorator}. * * @param {string} name The name of the constant. * @param {*} value The constant value. * @returns {Object} registered instance + * + * @example + * Here a some examples of creating constants: + *
+ *   $provide.constant('SHARD_HEIGHT', 306);
+ *   
+ *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
+ *   
+ *   $provide.constant('double', function(value) {
+ *     return value * 2;
+ *   });
+ * 
*/ @@ -416,17 +519,29 @@ function annotate(fn) { * @methodOf AUTO.$provide * @description * - * Decoration of service, allows the decorator to intercept the service instance creation. The - * returned instance may be the original instance, or a new instance which delegates to the - * original instance. + * Register a **service decorator** with the {@link AUTO.$injector $injector}. A service decorator + * intercepts the creation of a service, allowing it to override or modify the behaviour of the + * service. The object returned by the decorator may be the original service, or a new service object + * which replaces or wraps and delegates to the original service. * * @param {string} name The name of the service to decorate. * @param {function()} decorator This function will be invoked when the service needs to be - * instantiated. The function is called using the {@link AUTO.$injector#invoke - * injector.invoke} method and is therefore fully injectable. Local injection arguments: + * instantiated and should return the decorated service instance. The function is called using + * the {@link AUTO.$injector#invoke injector.invoke} method and is therefore fully injectable. + * Local injection arguments: * * * `$delegate` - The original service instance, which can be monkey patched, configured, * decorated or delegated to. + * + * @example + * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting + * calls to {@link ng.$log#error $log.warn()}. + *
+ *   $provider.decorator('$log', ['$delegate', function($delegate) {
+ *     $delegate.warn = $delegate.error;
+ *     return $delegate;
+ *   }]);
+ * 
*/ -- cgit v1.2.3