From 2e90cdc3d4dff966faed97d3a566e9d9c00c9794 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Mon, 27 Feb 2012 12:14:48 -0800 Subject: docs(dependency injecton): rewrite --- .../guide/dev_guide.di.understanding_di.ngdoc | 193 --------------------- 1 file changed, 193 deletions(-) delete mode 100644 docs/content/guide/dev_guide.di.understanding_di.ngdoc (limited to 'docs/content/guide/dev_guide.di.understanding_di.ngdoc') 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: - - - -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: - -
-function myFn(a,b){}
-expect(myFn.toString()).toEqual('function myFn(a,b){}');
-
- -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: - -
-// 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'];
-
- -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: - -
-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
-});
-
- -... 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`: - -
-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
-});
-
- -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: - -
-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
-  });
-});
-
- - -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: - -
- 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
- });
-
- - -## Related Topics - -* {@link dev_guide.services Angular Services} - -## Related API - -* {@link api/angular.module.ng Services API} -- cgit v1.2.3