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 <pre> tags.
Move the detailed explanations into each function's documentation block.
Improve the overview and list the constituent functions by significance.

Closes #4302
This commit is contained in:
Pete Bacon Darwin
2013-10-10 16:46:59 +01:00
parent 85b7d24357
commit 770353df19

View File

@@ -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.
* 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}.
*
* 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.
* 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.
*
* <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>
* * {@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()}.
*
* <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>
*/
/**
@@ -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
* <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>
*/
@@ -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.
* <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>
*/
@@ -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.
* <pre>
* $provide.constant('ADMIN_USER', 'admin');
*
* $provide.constant('RoleLookup', { admin: 0, writer: 1, reader: 2 });
*
* $provide.constant('halfOf', function(value) {
* return value / 2;
* });
* </pre>
*/
@@ -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:
* <pre>
* $provide.constant('SHARD_HEIGHT', 306);
*
* $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
*
* $provide.constant('double', function(value) {
* return value * 2;
* });
* </pre>
*/
@@ -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()}.
* <pre>
* $provider.decorator('$log', ['$delegate', function($delegate) {
* $delegate.warn = $delegate.error;
* return $delegate;
* }]);
* </pre>
*/