mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 15:40:22 +00:00
96 lines
4.1 KiB
Text
96 lines
4.1 KiB
Text
@ngdoc overview
|
|
@name Developer Guide: DI: Understanding DI in Angular
|
|
@description
|
|
|
|
|
|
While DI is widely used in statically typed languages such as Java or C++, it has not been widely
|
|
used in JavaScript. Angular brings the benefits of DI into JavaScript apps.
|
|
|
|
In angular, DI is implemented as a subsystem that manages dependencies between services,
|
|
controllers, widgets, and filters.
|
|
|
|
Services are objects that handle common tasks in web applications. Angular provides several {@link
|
|
api/angular.module.ng built-in services}, and you can create your
|
|
{@link dev_guide.services.creating_services own custom services}.
|
|
|
|
The main job of angular's DI subsystem is to provide services to angular components that depend on
|
|
them. The way the DI subsystem provides services is as follows: all services are registered with
|
|
angular's {@link api/angular.module.ng service API}, and all components that depend on services
|
|
define those dependencies as a property (`$inject`). With this information, the DI subsystem
|
|
manages the creation of service objects and the provision of those objects to the components that
|
|
need them, at the time they need them. The following illustration steps through the sequence of
|
|
events:
|
|
|
|
<img src="img/guide/di_sequence_final.png">
|
|
|
|
In the illustration above, the dependency injection sequence proceeds as follows:
|
|
|
|
1. Module "phonecat" is created and all the service providers are registered with this module.
|
|
(the "ng" module is created by Angular behind the scenes as well)
|
|
2. `ng:app` triggers bootstrap sequence on given element, during which angular creates injector,
|
|
loads "phonecat" and "ng" modules and compiles the template.
|
|
3. The `ng:controller` directive implicitly creates a new child scope and instantiates
|
|
`PhoneListCtrl` controller.
|
|
4. Injector identifies the `$http` service as `PhoneListCtrl` controller's only dependency.
|
|
5. Injector checks its instances cache whether the `$http` service has already been instantiated.
|
|
If not uses the provider from the available modules to construct it.
|
|
6. Injector provides the instance of `$http` service to the `PhoneListCtrl` controller constructor.
|
|
|
|
|
|
## How Scope Relates to DI
|
|
|
|
The root scope of the application is just a service that is available for injection to any part of
|
|
the application under the service name "$rootScope".
|
|
|
|
|
|
## Inferring dependencies from the signature of the factory function or constructor
|
|
|
|
**EXPERIMENTAL FEATURE**: This is an experimental feature. See the important note at the end of
|
|
this section for drawbacks.
|
|
|
|
We resort to `$inject` and our own annotation because there is no way in JavaScript to get a list
|
|
of arguments. Or is there? It turns out that calling `.toString()` on a function returns the
|
|
function declaration along with the argument names as shown below:
|
|
|
|
<pre>
|
|
function myFn(a,b){}
|
|
expect(myFn.toString()).toEqual('function myFn(a,b){}');
|
|
</pre>
|
|
|
|
This means that angular can infer the function names after all and use that information to generate
|
|
the `$inject` annotation automatically. Therefore the following two function definitions are
|
|
equivalent:
|
|
|
|
<pre>
|
|
// given a user defined service
|
|
angular.module('module1', [], function($provide) {
|
|
$provide.factory('serviceA', ...);
|
|
});
|
|
|
|
// inject '$window', 'serviceA', curry 'name';
|
|
function fnA($window, serviceA, name){};
|
|
fnA.$inject = ['$window', 'serviceA'];
|
|
|
|
// inject '$window', 'serviceA', curry 'name';
|
|
function fnB($window, serviceA_, name){};
|
|
// implies: fnB.$inject = ['$window', 'serviceA'];
|
|
</pre>
|
|
|
|
If angular does not find a `$inject` annotation on the function, then it calls the `.toString()`
|
|
method and tries to infer what should be injected by using function argument names as dependency
|
|
identifiers.
|
|
|
|
**IMPORTANT**
|
|
Minifiers/obfuscators change the names of function arguments and will therefore break the `$inject`
|
|
inference. For this reason, either explicitly declare the `$inject` or do not use
|
|
minifiers/obfuscators. In the future, we may provide a pre-processor which will scan the source
|
|
code and insert the `$inject` into the source code so that it can be minified/obfuscated.
|
|
|
|
|
|
## Related Topics
|
|
|
|
* {@link dev_guide.services Angular Services}
|
|
|
|
## Related API
|
|
|
|
* {@link api/angular.module.ng Services API}
|