Recently I was reading the authoritative AngularJS guide. Due to various reasons (mainly because I don’t have money, I hate it, so I chose to download the electronic version online (because it doesn’t cost money, haha...). The font is quite clear and the overall effect is pretty good. However, when I saw the total page number in the upper left corner, 479 pages...479...479...479...Is it true that half of my little heart was penetrated? The upper body was petrified? The kind of tangled feeling that I really want to learn but don’t want to learn the page number but don’t want to learn it? Is it more complicated than quarreling with my girlfriend? The e-books I usually read are not more than 3 with a hundred digits! Alas, forgive me, I should read a few more books about the Xinhua Dictionary...
Fortunately, before reading e-books, I was a little bit basic. I had learned a little while watching videos, from two-way data binding to services, and then to the instruction system, I had more or less contact. In addition, during a web special course selection assignment, a simple student class management system was built through AngularJS on the front end and NodeJS on the backend and Mongoose on the backend. Because I don’t have money, I can only place it on GitHub. GitHub address: Student management system, welcome to fork, let’s get to the topic below...
=============================================================================================================
There are usually three ways for an object to gain control over its dependency:
(1) Create dependencies internally;
(2) References through global variables;
(3) Pass through parameters where required.
Dependency injection is achieved in the third way. The other two methods will bring various problems, such as polluting the global scope, making isolation extremely difficult, etc. Dependency injection is a design pattern that removes hard-coded dependencies, so that dependencies can be changed or even removed at runtime.
The ability to modify dependencies at runtime is ideal for testing because it allows us to create an isolated environment where mocked objects can be used instead of real objects in the production environment.
From a functional perspective, dependency injection will automatically find the dependency in advance and inform the dependent resource of the injection target, so that the resource can be injected immediately when the target needs it.
When writing components that depend on other objects or libraries, we need to describe the dependencies between components. During runtime, the injector creates an instance of the dependency and is responsible for passing it to the dependent consumer.
// Excellent example from Angular documentation function SomeClass(greeter) {this.greeter = greeter;}SomeClass.prototype.greetName = function(name) {this.greeter.greet(name);};//Note that the sample code creates a controller on the global scope, which is not a good idea, it is just for the convenience of the demonstration.SomeClass is able to access the internal greeter at runtime, but it doesn't care how to get a reference to the greeter. To obtain a reference to the greeter instance, the creator of SomeClass is responsible for constructing its dependencies and passing them in.
For the above reasons, AngularJS uses $injetor (injector service) to manage queries and instantiation of dependencies. In fact, $injetor is responsible for instantiating all components in AngularJS, including the application's modules, instructions, and controllers.
At runtime, $injetor is responsible for instantiating any module when it starts and passing all the dependencies it needs into.
For example, the following code. This is a simple application that declares a module and a controller:
angular.module('myApp', []).factory('greeter', function() {return {greet: function(msg) {alert(msg);}}}).controller('MyController',function($scope, greeter) {$scope.sayHello = function() {greeter.greet("Hello!");};});When AngularJS instantiates this module, it looks for greeter and naturally passes references to it:
<div ng-app="myApp"><div ng-controller="MyController"><button ng-click="sayHello()">Hello</button></div></div>
Internally, the processing process of AngularJS is as follows:
// Use the injector to load the application var injector = angular.injector(['ng', 'myApp']);// Load the $controller service through the injector var $controller = injector.get('$controller');// Load the controller and pass in a scope, just like AngularJS does at runtime var scope = injector.get('$rootScope').$new();var MyController = $controller('MyController', {$scope: scope});The above code does not specify how to find greeter, but it does work properly because $injector will be responsible for finding and loading it for us.
AngularJS extracts the parameter list from the passed function during instantiation through the annotate function. Enter the following code into Chrome's developer tools to view this function:
> injector.annotate(function($q, greeter) {}) ["$q", "greeter"]In any AngularJS application, $injector is working, whether we know or not. When writing a controller, if no [] tag is used or explicit declaration is made, $injector tries to infer dependencies by parameter names.
Inferred Injection Statement
If there is no explicit declaration, AngularJS assumes that the parameter name is the name of the dependency. Therefore, it will internally call the toString() method of the function object, analyze and extract the function parameter list, and inject these parameters into the object instance through $injector. The injection process is as follows:
injector.invoke(function($http, greeter) {});Note that this process is only applicable to uncompressed and obfuscated code, as AngularJS requires a raw uncompressed parameter list for parsing. With this process of inferring based on parameter names, the order of parameters is of little significance, because AngularJS will help us inject properties in the correct order.
Explicitly inject declarations
AngularJS provides explicit methods to clearly define the dependencies that a function needs to use when it is called. Declaring dependencies in this way can still work properly even if the source code is compressed and the parameter name changes. The $inject property can be used to implement the function of explicit injection of declarations. The $inject property of a function object is an array, the type of the array element is a string, and their values are the name of the service that needs to be injected.
Here is the sample code:
var aControllerFactory =function aController($scope, greeter) {console.log("LOADED controller", greeter);// ...Controller};aControllerFactory.$inject = ['$scope', 'greeter']; // Greeter service console.log("greeter service");}// Our application controller angular.module('myApp', []).controller('MyController', aControllerFactory).factory('greeter', greeterService);// Get the injector and create a new scope var injector = angular.injector(['ng', 'myApp']),controller = injector.get('$controller'),rootScope = injector.get('$rootScope'),newScope = rootScope.$new();// Call controller controller('MyController', {$scope: newScope});For this declaration method, the order of parameters is very important, because the order of the $inject array elements must correspond one by one to the order of injected parameters. This declaration method can be run in compressed code because the relevant information of the declaration is already bound to the function itself.
Intra-line injection statement
The last way to inject declarations provided by AngularJS is an inline injection declaration that can be used at any time. This method is actually a syntactic sugar, which is exactly the same as the principle mentioned above for injecting declarations through the $inject property, but allows us to pass parameters from within the line when the function is defined. Additionally, it avoids the use of temporary variables during the definition process.
When defining an AngularJS object, the in-line declaration allows us to pass an array of parameters directly instead of a function. The elements of the array are strings, which represent the names of dependencies that can be injected into the object. The last parameter is the object object itself of dependency injection.
Examples are as follows:
angular.module('myApp').controller('MyController', ['$scope', 'greeter', function($scope, greeter) {}]);Since what needs to be processed is a list of strings, inline injection declarations can also run normally in the compressed code. It is usually used by brackets and the [] symbol that declares the array.
The above AngularJS dependency injection is all the content I share with you. I hope you can give you a reference and I hope you can support Wulin.com more.