diff options
Diffstat (limited to 'docs/content/guide/dev_guide.di.understanding_di.ngdoc')
| -rw-r--r-- | docs/content/guide/dev_guide.di.understanding_di.ngdoc | 193 |
1 files changed, 0 insertions, 193 deletions
diff --git a/docs/content/guide/dev_guide.di.understanding_di.ngdoc b/docs/content/guide/dev_guide.di.understanding_di.ngdoc deleted file mode 100644 index 23b22884..00000000 --- a/docs/content/guide/dev_guide.di.understanding_di.ngdoc +++ /dev/null @@ -1,193 +0,0 @@ -@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. `ngApp` triggers bootstrap sequence on given element, during which angular creates injector, -loads "phonecat" and "ng" modules and compiles the template. -3. The `ngController` 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. - - -### Dependency inference and variable name shadowing - -During inference, the injector considers argument names with leading and trailing underscores to be -equivivalent to the name without these underscores. For example `_fooSvc_` argument name is treated -as if it was `fooSvc`, this is useful especially in tests where variable name shadowing can cause -some friction. This is best illustrated on examples: - -When testing a service, it's common to need a reference to it in every single test. This can be -done in jasmine with DI inference like this: - -<pre> -describe('fooSvc', function() { - it('should do this thing', inject(function(fooSvc) { - //test fooSvc - })); - - it('should do that thing', inject(function(fooSvc) { - //test fooSvc - })); - - // more its -}); -</pre> - -... but having to inject the service over and over gets easily tiresome. - -It's likely better to rewrite these tests with a use of jasmine's `beforeEach`: - -<pre> -describe('fooSvc', function() { - var fooSvc; - - beforeEach(inject(function(fooSvc) { - fooSvc = fooSvc; // DOESN'T WORK! outer fooSvc is being shadowed - })); - - it('should do this thing', function() { - //test fooSvc - }); - - it('should do that thing', function() { - //test fooSvc - }); - - // more its -}); -</pre> - -This obviously won't work because `fooSvc` variable in the describe block is being shadowed by the -`fooSvc` argument of the beforeEach function. So we have to resort to alternative solutions, like -for example use of array notation to annotate the beforeEach fn: - -<pre> -describe('fooSvc', function() { - var fooSvc; - - beforeEach(inject(['fooSvc', function(fooSvc_) { - fooSvc = fooSvc_; - }])); - - it('should do this thing', function() { - //test fooSvc - }); - - it('should do that thing', function() { - //test fooSvc - }); -}); -</pre> - - -That's better, but it's still annoying, especially if you have many services to inject. - -To resolve this shadowing problem, the injector considers `_fooSvc_` argument names equal to -`fooSvc`, so the test can be rewritten like this: - -<pre> - describe('fooSvc', function() { - var fooSvc; - - beforeEach(inject(function(_fooSvc_) { - fooSvc = _fooSvc_; - })); - - it('should do this thing', function() { - //test fooSvc - }); - - it('should do that thing', function() { - //test fooSvc - }); - - // more its - }); -</pre> - - -## Related Topics - -* {@link dev_guide.services Angular Services} - -## Related API - -* {@link api/angular.module.ng Services API} |
