Let's say I have 3 modules:
angular.module('A', [])
angular.module('B', ['A'])
angular.module('C', ['B', 'A'])
In terms of dependency injection, will B and C share the same instance of module A, or will separate instances be injected into each of them?
To summarize your question, answer would be only one instance.
In fact it is this way. Angular app resolves dependencies via injector. Only one injector is created per app. Technically you can have only one ng-app, but you can have multiple apps by using manual bootstrapping, in that case there will be an injector created for each app and those 2 apps will not share any dependencies.
In general case where there is only rootElement bootstrapped as an angular app. It resolves the modules starting the module that has been bootstrapped (starting from the bottom of the dependency chain). Any services/controllers/filters etc registered under that module or any dependent modules under that dependency chain will be bundled together in the injector cache(instantiated lazily when injected) just once. For example say you have a service myService registered under module A. No matter how many places you list A as dependency ultimately only one instance of its constructor will be available, and service being a singleton everyone gets the same singleton instance.
Official Doc:
Modules can list other modules as their dependencies. Depending on a module implies that the required module needs to be loaded before the requiring module is loaded. In other words the configuration blocks of the required modules execute before the configuration blocks of the requiring module. The same is true for the run blocks. Each module can only be loaded once, even if multiple other modules require it.
Related
I cannot find example which shows the last step of building/using custom module -- referencing it in code. Let's say I have such line in my custom module:
angular.module('shared', []).factory('Factory', [Module]);
Then in my main app, I declared the dependency:
let app = angular.module('admin',[
"shared",
]);
So far, so good. The question is how do I access this shared? In my case it is undefined. What do I miss?
You can now inject elements in admin module that are registered in shared, like factories, controllers, providers, directives etc.
So you can inject Factory to some factory in your admin module.
Currently the only way that I know of to make module dependencies available is to specify them when a module is declared. e.g.:
angular.module("myApp",["myDependentModule"]);
This becomes a problem when the app gets large and modules have a lot of dependencies, libraries that must be loaded. If these libraries aren't required for any of the modules that the first page the user visits, it seems that those dependencies could be deferred to improve load time.
Any advice would be appreciated.
Use angular.injector(...)
https://docs.angularjs.org/api/ng/function/angular.injector
Mention and example is here:
var injector = angular.injector(['someModule']);
var someService = injector.get('someService');
AngularJS - Injecting factory from another module into a provider
you can use lazy load moduls.
https://oclazyload.readme.io/docs
I'm confused about something. Some dependencies have to be injected to the main module. For example:
angular.module("app", ["ui.router", "ui.bootstrap", "toaster"]);
Whereas some other dependencies can just be injected into the controllers, but don't need to be injected into the main module. For example:
angular.module("app").controller("newCtrl", ["$q", newCtrl);
I'm having difficulties understanding why. Any help will be much appreciated.
$q a service within the core ng module, per the documentation.
All services within the ng module are bootstrapped and registered when the angular.js file is loaded and parsed. This allows you to inject them anywhere in your app.
However, the three examples you have listed above are all external, modular dependencies. They need to be explicitly registered into your application so that the components within are available when the $injector service attempts to resolve them.
You inject modules into other modules.
You inject providers, services, and factories that are included in those modules into the specific controllers.
In Angular, you define a module like so:
angular.module('MyModule1', []);
Notice how module function takes two arguments. Second argument being the array of other modules this module is dependent on. This construct is for setting a module.
Once the module is defined, you can attach controller, services etc. to the module.
angular
.module('MyModule1')
.service('MyService1');
Notice, how this time only one argument was give to the module function. That means you are getting an already registered module.
Lets say you create another module MyModule2, but MyModule2 needs to use the services defined by the MyModule1.
You just set the module MyModule2 with MyModule1 as its dependency.
angular.module('MyModule2', ['MyModule1']);
Now, you want to create a controller (or a directive, or a service, whatever) in MyModule2 that actually makes use of the service MyService1 defined in MyModule1.
That's where the Dependency Injection (DI) of Angular comes in. You define your controller with the service name as function parameter and when Angular instantiates your controller, it makes sure the service instance is found and provided to your controller.
angular
.module('MyModule2')
.controller('MyController2', function (myService1) {
// Hey I can use myService1
// Dependency Injection FTW!
});
I didn't understand how work modular depending.
I have 3 modules, they are dependent on each other, as shown in the picture.
"App" module includes "module1" and "module2".
"module2" includes "core" module. There are source on plunker.
angular.module("core", []).factory("HelloWorld", function() {
return function () {
alert('Hello World!')
}
});
angular.module("module1", []).controller("main", function(HelloWorld){
HelloWorld();
});
angular.module("module2", ["core"]);
angular.module("app", ["module1", "module2"]);
If I inject service from module core to module "module1" it is work fine. But "core" module not depend in module "module1". Why it happening?
Since your App module depends on Core module (indirectly through Module 2), the services in Core module are available anywhere inside your App module (including Module 1).
This is because Angular will first load all modules and then start instantiating their components and resolving injected dependencies.
Yet, if you indeed need Core services in Module 1, you should make it dependent on the Core module as well. That way your application won't break if Module 2 is modified at a later time (or removed altogether) and your Module 1 will be more self-contained and reusable (e.g. you could use it with a different application that does not depend on the Core module).
In general, you should not rely on "indirect" dependencies. Each module should explicitly declare its dependencies.
Angular is smart enough to only load a module if it is not already loaded, so there is no overhead.
Quoting from the Developer Guide's section on modules:
Modules can list other modules as their dependencies. Depending on a module implies that required module needs to be loaded before the requiring module is loaded. In other words the configuration blocks of the required modules execute before the configuration blocks of the requiring module. The same is true for the run blocks. Each module can only be loaded once, even if multiple other modules require it.
(emphasis mine)
I am working on some E2E tests for AngularJS.
I have implemented a $httpBackend ngMockE2E.
This works well, however in some instances HTTP requests are being made before my mocks have been completely set up.
The Mock is set up as:
angular.module('Mock', ['ngMockE2E']).
run(function($httpBackend) {
$httpBackend.whenPOST('/path1').respond({ exampleresponse: 'valid' });
$httpBackend.whenPOST('/path2').respond({ exampleresponse: 'valid' });
And it is used as below:
angular.module('Application', ['FirstDependency', 'Mock', 'ThirdDependency']);
However FirstDependency and ThirdDependency can make HTTP requests which sometimes happen before the Mock .run() block has been executed. This results in request errors.
Am I setting up my mocks correctly? What is the best way to ensure my mocks are loaded in the right order?
This is what the doc says:
Dependencies:
Modules can list other modules as their dependencies.
Depending on a module implies that required module needs to be loaded
before the requiring module is loaded. In other words the
configuration blocks of the required modules execute before the
configuration blocks of the requiring module. The same is true for the
run blocks. Each module can only be loaded once, even if multiple
other modules require it.
However what it doesn't say is that it will first execute the config blocks for all modules (dependencies first) and then it will execute all the other blocks in a row for each module in turn. For an illustration of this take a look at this jsfiddle:
http://jsfiddle.net/9FJnZ/2/