Skip to content

Commit 770353d

Browse files
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 angular#4302
1 parent 85b7d24 commit 770353d

File tree

1 file changed

+204
-89
lines changed

1 file changed

+204
-89
lines changed

src/auto/injector.js

Lines changed: 204 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -253,83 +253,37 @@ function annotate(fn) {
253253
*
254254
* @description
255255
*
256-
* Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.
257-
* The providers share the same name as the instance they create with `Provider` suffixed to them.
258-
*
259-
* A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of
260-
* a service. The Provider can have additional methods which would allow for configuration of the provider.
261-
*
262-
* <pre>
263-
* function TrackingProvider() {
264-
* this.$get = function($http) {
265-
* var observed = {};
266-
* return {
267-
* event: function(event) {
268-
* var current = observed[event];
269-
* return observed[event] = current ? current + 1 : 1;
270-
* },
271-
* save: function() {
272-
* $http.post("/track",observed);
273-
* }
274-
* };
275-
* };
276-
* }
277-
*
278-
* describe('Tracking', function() {
279-
* var mocked;
280-
* beforeEach(module(function($provide) {
281-
* $provide.provider('tracking', TrackingProvider);
282-
* mocked = {post: jasmine.createSpy('postSpy')};
283-
* $provide.value('$http',mocked);
284-
* }));
285-
* it('allows events to be tracked', inject(function(tracking) {
286-
* expect(tracking.event('login')).toEqual(1);
287-
* expect(tracking.event('login')).toEqual(2);
288-
* }));
289-
*
290-
* it('posts to save', inject(function(tracking) {
291-
* tracking.save();
292-
* expect(mocked.post.callCount).toEqual(1);
293-
* }));
294-
* });
295-
* </pre>
296-
*
297-
* There are also shorthand methods to define services that don't need to be configured beyond their `$get()` method.
298-
*
299-
* `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.
300-
*
301-
* <pre>
302-
* function TrackingProvider($http) {
303-
* var observed = {};
304-
* this.event = function(event) {
305-
* var current = observed[event];
306-
* return observed[event] = current ? current + 1 : 1;
307-
* };
308-
* this.save = function() {
309-
* $http.post("/track",observed);
310-
* };
311-
* }
312-
* $provider.service('tracking',TrackingProvider);
313-
* </pre>
314-
*
315-
* `factory()` registers a function whose return value is the instance. Again, you can specify services that will be provided by the injector.
316-
*
317-
* <pre>
318-
* function TrackingProvider($http) {
319-
* var observed = {};
320-
* return {
321-
* event: function(event) {
322-
* var current = observed[event];
323-
* return observed[event] = current ? current + 1 : 1;
324-
* },
325-
* save: function() {
326-
* $http.post("/track",observed);
327-
* }
328-
* };
329-
* }
330-
* $provider.factory('tracking',TrackingProvider);
331-
* </pre>
332-
*
256+
* The {@link AUTO.$provide $provide} service has a number of methods for registering components with
257+
* the {@link AUTO.$injector $injector}. Many of these functions are also exposed on {@link angular.Module}.
258+
*
259+
* An Angular **service** is a singleton object created by a **service factory**. These **service
260+
* factories** are functions which, in turn, are created by a **service provider**.
261+
* The **service providers** are constructor functions. When instantiated they must contain a property
262+
* called `$get`, which holds the **service factory** function.
263+
*
264+
* When you request a service, the {@link AUTO.$injector $injector} is responsible for finding the
265+
* correct **service provider**, instantiating it and then calling its `$get` **service factory**
266+
* function to get the instance of the **service**.
267+
*
268+
* Often services have no configuration options and there is no need to add methods to the service
269+
* provider. The provider will be no more than a constructor function with a `$get` property. For
270+
* these cases the {@link AUTO.$provide $provide} service has additional helper methods to register
271+
* services without specifying a provider.
272+
*
273+
* * {@link AUTO.$provide#provider provider(provider)} - registers a **service provider** with the
274+
* {@link AUTO.$injector $injector}
275+
* * {@link AUTO.$provide#constant constant(obj)} - registers a value/object that can be accessed by
276+
* providers and services.
277+
* * {@link AUTO.$provide#value value(obj)} - registers a value/object that can only be accessed by
278+
* services, not providers.
279+
* * {@link AUTO.$provide#factory factory(fn)} - registers a service **factory function**, `fn`, that
280+
* will be wrapped in a **service provider** object, whose `$get` property will contain the given
281+
* factory function.
282+
* * {@link AUTO.$provide#service service(class)} - registers a **constructor function**, `class` that
283+
* will be wrapped in a **service provider** object, whose `$get` property will instantiate a new
284+
* object using the given constructor function.
285+
*
286+
* See the individual methods for more information and examples.
333287
*/
334288

335289
/**
@@ -338,7 +292,18 @@ function annotate(fn) {
338292
* @methodOf AUTO.$provide
339293
* @description
340294
*
341-
* Register a provider for a service. The providers can be retrieved and can have additional configuration methods.
295+
* Register a **provider function** with the {@link AUTO.$injector $injector}. Provider functions are
296+
* constructor functions, whose instances are responsible for "providing" a factory for a service.
297+
*
298+
* Service provider names start with the name of the service they provide followed by `Provider`.
299+
* For example, the {@link ng.$log $log} service has a provider called {@link ng.$logProvider $logProvider}.
300+
*
301+
* Service provider objects can have additional methods which allow configuration of the provider and
302+
* its service. Importantly, you can configure what kind of service is created by the `$get` method,
303+
* or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a method
304+
* {@link ng.$logProvider#debugEnabled debugEnabled}
305+
* which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
306+
* console or not.
342307
*
343308
* @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.
344309
* @param {(Object|function())} provider If the provider is:
@@ -349,6 +314,70 @@ function annotate(fn) {
349314
* {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.
350315
*
351316
* @returns {Object} registered provider instance
317+
318+
* @example
319+
*
320+
* The following example shows how to create a simple event tracking service and register it using
321+
* {@link AUTO.$provide#provider $provide.provider()}.
322+
*
323+
* <pre>
324+
* // Define the eventTracker provider
325+
* function EventTrackerProvider() {
326+
* var trackingUrl = '/track';
327+
*
328+
* // A provider method for configuring where the tracked events should been saved
329+
* this.setTrackingUrl = function(url) {
330+
* trackingUrl = url;
331+
* };
332+
*
333+
* // The service factory function
334+
* this.$get = ['$http', function($http) {
335+
* var trackedEvents = {};
336+
* return {
337+
* // Call this to track an event
338+
* event: function(event) {
339+
* var count = trackedEvents[event] || 0;
340+
* count += 1;
341+
* trackedEvents[event] = count;
342+
* return count;
343+
* },
344+
* // Call this to save the tracked events to the trackingUrl
345+
* save: function() {
346+
* $http.post(trackingUrl, trackedEvents);
347+
* }
348+
* };
349+
* }];
350+
* }
351+
*
352+
* describe('eventTracker', function() {
353+
* var postSpy;
354+
*
355+
* beforeEach(module(function($provide) {
356+
* // Register the eventTracker provider
357+
* $provide.provider('eventTracker', EventTrackerProvider);
358+
* }));
359+
*
360+
* beforeEach(module(function(eventTrackerProvider) {
361+
* // Configure eventTracker provider
362+
* eventTrackerProvider.setTrackingUrl('/custom-track');
363+
* }));
364+
*
365+
* it('tracks events', inject(function(eventTracker) {
366+
* expect(eventTracker.event('login')).toEqual(1);
367+
* expect(eventTracker.event('login')).toEqual(2);
368+
* }));
369+
*
370+
* it('saves to the tracking url', inject(function(eventTracker, $http) {
371+
* postSpy = spyOn($http, 'post');
372+
* eventTracker.event('login');
373+
* eventTracker.save();
374+
* expect(postSpy).toHaveBeenCalled();
375+
* expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
376+
* expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
377+
* expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
378+
* }));
379+
* });
380+
* </pre>
352381
*/
353382

354383
/**
@@ -357,12 +386,32 @@ function annotate(fn) {
357386
* @methodOf AUTO.$provide
358387
* @description
359388
*
360-
* A service whose instance is the return value of `$getFn`. Short hand for configuring services if only `$get` method is required.
389+
* Register a **service factory**, which will be called to return the service instance.
390+
* This is short for registering a service where its provider consists of only a `$get` property,
391+
* which is the given service factory function.
392+
* You should use {@link AUTO.$provide#factory $provide.factor(getFn)} if you do not need to configure
393+
* your service in a provider.
361394
*
362395
* @param {string} name The name of the instance.
363396
* @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for
364397
* `$provide.provider(name, {$get: $getFn})`.
365398
* @returns {Object} registered provider instance
399+
*
400+
* @example
401+
* Here is an example of registering a service
402+
* <pre>
403+
* $provide.factory('ping', ['$http', function($http) {
404+
* return function ping() {
405+
* return $http.send('/ping');
406+
* };
407+
* }]);
408+
* </pre>
409+
* You would then inject and use this service like this:
410+
* <pre>
411+
* someModule.controller('Ctrl', ['ping', function(ping) {
412+
* ping();
413+
* }]);
414+
* </pre>
366415
*/
367416

368417

@@ -372,11 +421,34 @@ function annotate(fn) {
372421
* @methodOf AUTO.$provide
373422
* @description
374423
*
375-
* A service whose instance is created by invoking `constructor` with `new`. A short hand for registering services which use a constructor.
424+
* Register a **service constructor**, which will be invoked with `new` to create the service instance.
425+
* This is short for registering a service where its provider's `$get` property is the service
426+
* constructor function that will be used to instantiate the service instance.
427+
*
428+
* You should use {@link AUTO.$provide#service $provide.service(class)} if you define your service
429+
* as a type/class. This is common when using {@link http://coffeescript.org CoffeeScript}.
376430
*
377431
* @param {string} name The name of the instance.
378432
* @param {Function} constructor A class (constructor function) that will be instantiated.
379433
* @returns {Object} registered provider instance
434+
*
435+
* @example
436+
* Here is an example of registering a service using {@link AUTO.$provide#service $provide.service(class)}
437+
* that is defined as a CoffeeScript class.
438+
* <pre>
439+
* class Ping
440+
* constructor: (@$http)->
441+
* send: ()=>
442+
* @$http.get('/ping')
443+
*
444+
* $provide.service('ping', ['$http', Ping])
445+
* </pre>
446+
* You would then inject and use this service like this:
447+
* <pre>
448+
* someModule.controller 'Ctrl', ['ping', (ping)->
449+
* ping.send()
450+
* ]
451+
* </pre>
380452
*/
381453

382454

@@ -386,11 +458,29 @@ function annotate(fn) {
386458
* @methodOf AUTO.$provide
387459
* @description
388460
*
389-
* A short hand for configuring services if the `$get` method is a constant.
461+
* Register a **value service** with the {@link AUTO.$injector $injector}, such as a string, a number,
462+
* an array, an object or a function. This is short for registering a service where its provider's
463+
* `$get` property is a factory function that takes no arguments and returns the **value service**.
390464
*
465+
* Value services are similar to constant services, except that they cannot be injected into a module
466+
* configuration function (see {@link angular.Module#config}) but they can be overridden by an Angular
467+
* {@link AUTO.$provide#decorator decorator}.
468+
*
391469
* @param {string} name The name of the instance.
392470
* @param {*} value The value.
393471
* @returns {Object} registered provider instance
472+
*
473+
* @example
474+
* Here are some examples of creating value services.
475+
* <pre>
476+
* $provide.constant('ADMIN_USER', 'admin');
477+
*
478+
* $provide.constant('RoleLookup', { admin: 0, writer: 1, reader: 2 });
479+
*
480+
* $provide.constant('halfOf', function(value) {
481+
* return value / 2;
482+
* });
483+
* </pre>
394484
*/
395485

396486

@@ -400,13 +490,26 @@ function annotate(fn) {
400490
* @methodOf AUTO.$provide
401491
* @description
402492
*
403-
* A constant value, but unlike {@link AUTO.$provide#value value} it can be injected
404-
* into configuration function (other modules) and it is not interceptable by
405-
* {@link AUTO.$provide#decorator decorator}.
493+
* Register a **constant service**, such as a string, a number, an array, an object or a function, with
494+
* the {@link AUTO.$injector $injector}. Unlike {@link AUTO.$provide#value value} it can be injected
495+
* into a module configuration function (see {@link angular.Module#config}) and it cannot be
496+
* overridden by an Angular {@link AUTO.$provide#decorator decorator}.
406497
*
407498
* @param {string} name The name of the constant.
408499
* @param {*} value The constant value.
409500
* @returns {Object} registered instance
501+
*
502+
* @example
503+
* Here a some examples of creating constants:
504+
* <pre>
505+
* $provide.constant('SHARD_HEIGHT', 306);
506+
*
507+
* $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
508+
*
509+
* $provide.constant('double', function(value) {
510+
* return value * 2;
511+
* });
512+
* </pre>
410513
*/
411514

412515

@@ -416,17 +519,29 @@ function annotate(fn) {
416519
* @methodOf AUTO.$provide
417520
* @description
418521
*
419-
* Decoration of service, allows the decorator to intercept the service instance creation. The
420-
* returned instance may be the original instance, or a new instance which delegates to the
421-
* original instance.
522+
* Register a **service decorator** with the {@link AUTO.$injector $injector}. A service decorator
523+
* intercepts the creation of a service, allowing it to override or modify the behaviour of the
524+
* service. The object returned by the decorator may be the original service, or a new service object
525+
* which replaces or wraps and delegates to the original service.
422526
*
423527
* @param {string} name The name of the service to decorate.
424528
* @param {function()} decorator This function will be invoked when the service needs to be
425-
* instantiated. The function is called using the {@link AUTO.$injector#invoke
426-
* injector.invoke} method and is therefore fully injectable. Local injection arguments:
529+
* instantiated and should return the decorated service instance. The function is called using
530+
* the {@link AUTO.$injector#invoke injector.invoke} method and is therefore fully injectable.
531+
* Local injection arguments:
427532
*
428533
* * `$delegate` - The original service instance, which can be monkey patched, configured,
429534
* decorated or delegated to.
535+
*
536+
* @example
537+
* Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
538+
* calls to {@link ng.$log#error $log.warn()}.
539+
* <pre>
540+
* $provider.decorator('$log', ['$delegate', function($delegate) {
541+
* $delegate.warn = $delegate.error;
542+
* return $delegate;
543+
* }]);
544+
* </pre>
430545
*/
431546

432547

0 commit comments

Comments
 (0)