diff options
Diffstat (limited to 'src/auto/injector.js')
| -rw-r--r-- | src/auto/injector.js | 293 | 
1 files changed, 204 insertions, 89 deletions
| diff --git a/src/auto/injector.js b/src/auto/injector.js index 8bb35575..482c8861 100644 --- a/src/auto/injector.js +++ b/src/auto/injector.js @@ -269,83 +269,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. - * - * <pre> - *   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); - *     })); - *   }); - * </pre> - * - * 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. - * - *  <pre> - *    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); - *  </pre> - * - *  `factory()` registers a function whose return value is the instance. Again, you can specify services that will be provided by the injector. - * - *  <pre> - *    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); - *  </pre> - * + * 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.   */  /** @@ -354,7 +308,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: @@ -365,6 +330,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()}. + * + * <pre> + *  // 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 }); + *    })); + *  }); + * </pre>   */  /** @@ -373,12 +402,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  + * <pre> + *   $provide.factory('ping', ['$http', function($http) { + *     return function ping() { + *       return $http.send('/ping'); + *     }; + *   }]); + * </pre> + * You would then inject and use this service like this: + * <pre> + *   someModule.controller('Ctrl', ['ping', function(ping) { + *     ping(); + *   }]); + * </pre>   */ @@ -388,11 +437,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. + * <pre> + *   class Ping + *     constructor: (@$http)-> + *     send: ()=> + *       @$http.get('/ping') + *   + *   $provide.service('ping', ['$http', Ping]) + * </pre> + * You would then inject and use this service like this: + * <pre> + *   someModule.controller 'Ctrl', ['ping', (ping)-> + *     ping.send() + *   ] + * </pre>   */ @@ -402,11 +474,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. + * <pre> + *   $provide.constant('ADMIN_USER', 'admin'); + *    + *   $provide.constant('RoleLookup', { admin: 0, writer: 1, reader: 2 }); + *    + *   $provide.constant('halfOf', function(value) { + *     return value / 2; + *   }); + * </pre>   */ @@ -416,13 +506,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: + * <pre> + *   $provide.constant('SHARD_HEIGHT', 306); + *    + *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']); + *    + *   $provide.constant('double', function(value) { + *     return value * 2; + *   }); + * </pre>   */ @@ -432,17 +535,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()}. + * <pre> + *   $provider.decorator('$log', ['$delegate', function($delegate) { + *     $delegate.warn = $delegate.error; + *     return $delegate; + *   }]); + * </pre>   */ | 
