AngularJS invokeQueue and configBlocks - angularjs

AngularJs Source code deep dive - What does invokeQueue and configBlocks do during angularjs bootstrapping? I see they are passed to arguments for runInvokeQueue function inside loadModules.

configBlocks stores the list of services instantiated during module configuration:
angular.module("ng")._configBlocks[0][0]
invokeQueue stores the list of methods invoked after the module is loaded:
var foo = angular.module("ng");
foo.constant(alert)
foo._invokeQueue[0]
foo._invokeQueue[0][2][0]
The module definition is situated at the first lines of AngularJS source. As the documentation says, the life span of every module operation can be divided into two phases. The config phase and the run phase. The object exposed by calling the angular.module() constructor provides us with these two methods. The functionality of the run method is pretty obvious out of the source. It simply puts the config function passed to the private list of run blocks. The config method, on the contrary, is not so obvious. Here is, what the config method does:
The invokeLater private method inserts the combination of provider and its method to the internal module queue to be invoked later during the injector instantiation. The modules would be totally useless, if it weren't for the injector. The CreateInjector function is the concrete implementation and it has the private method loadModules.
The loadModules function does, among other, the kickoff of modules which are passed to it. It returns one array of all the run blocks of all modules which are dependent on each other. The injector calls them through its invoke method. Last but not least, the loadModules function, during its iteration through all dependent modules, calls their functions stored at _invokeQueue and _configBlock respectively. The run blocks are called in the last position. This means all services and methods of the modules are already exposed and ready for use. On the contrary, the config method only works with providers exposed by the module. The constructors of the providers are stored in the _invokeQueue of the module.
Two injectors
The first injector, that is not exposed publicly, is an injector of providers. The second one is an instance injector. The instance injector asks the provider cache for the constructors needed. Then it calls the proper part of the provider and creates an instance. The instance injector searches in the provider cache before asking for the provider injector. The module.provider method exposes the provider injector's provider method, which at a closer look says a lot about the life cycle of services.
Even other parts of angular constructs, like directives and controllers, are registered as providers in the provider's cache. The $compileProvider itself is then registered like any other provider through $provide.provider method. As a matter of fact, module.factory, module.service and module.provider store an instance in the provider cache as a first step. But it is an instance injector that we have at our disposal. The instance injector asks the provider cache as a first step and then calls the invoke method, which takes care of the dependencies.
References
Modules and injector
Configuring a Provider
fix(injector): invoke config blocks for module after all providers
Loading an AngularJS controller dynamically

Related

Selectively Mock Services when Testing Angular with Karma

While there have been many questions around mocking an individual Angular service in Karma, I am having an issue with making my mocks more ubiquitous throughout testing my application.
In my current setup, I have a module called serviceMocks that includes a factory with a mock of each service in the application.
Contrived example:
angular.module('serviceMocks',['ngMock'])
.factory('myServiceOne', function() {...})
.factory('myServiceTwo', function($httpBackend,$q) {...})
This works great when testing controllers and directives which may use one or more services as a dependency. I include my app's module and the serviceMocks module within my testfile, and each service is properly substituted.
beforeEach(module('myApp'));
beforeEach(module('serviceMocks'));
it('properly substitutes mocks throughout my tests', function() {...});
However, when testing a service itself I cannot include the serviceMocks module, as the service I am testing is substituted by its mock making the tests useless. However, I would still like all other services mocked as a service may depend on one or more services for its execution.
One way I thought of doing this was to make my service mocks globally available, perhaps by attaching an object to window that holds the mocks. I could then include the mocks individually when testing services like so:
beforeEach(module('myApp', function($provide) {
$provide.value('myServiceOne',window.mocks.myServiceOneMock);
$provide.value('myServiceTwo',window.mocks.myServiceTwoMock);
});
However this approach did not work, because some of the mocks use $q or other angular services to function properly, and these services are not properly injected when simply attaching the factory object to the window.
I am looking for a way to test services while having a single location to define mocks for all services. Possibilities I imagine but have been unable to succeed with:
A) Have the serviceMocks module's .run() block run before the
config stage for myApp's module. (In which case I could attach
each service to the window as the angular dependencies would be
properly injected, and inject each as shown above)
B) Be able to override the service that I'm testing with its actual implementation in the test files of each service
C) Otherwise be able to define and access these mocks globally, while still ensuring each mock has access to certain angular services such as $q.
The question contains a clue to the answer. If serviceMocks module causes design issues, using it is a mistake.
The proper pattern is to have one module per unit (mocked service in this case). ngMock is not needed, it is loaded automatically in Jasmine tests. The modules can be used one by one:
beforeEach(module('app', 'serviceOneMock', 'serviceTwoMock'));
Or joined together:
angular.module('serviceMocks', ['serviceOneMock', 'serviceTwoMock'])
There are not so many cases when serviceMocks module should exist at all. Just because a decision which services should be mocked and which should not is made for each describe block.
Most times mocked services are individual for current spec or depend on local variables. In this case the services are mocked in-place:
var promiseResult;
beforeEach(module('app'));
beforeEach(module({ foo: 'instead of $provide.value(...)' });
beforeEach(($provide) => {
$provide.factory('bar', ($q) => {
return $q.resolve(promiseResult);
}
});
...
Doing this in dedicated serviceOneMock, etc. modules may require mocked services to be refactored any moment it becomes obvious they are too generic and don't suit the case well.
If mocked service is used more than once in specs with slightly different behaviour and results in WET tests, it is better to make a helper function that will generate it for current spec rather than hard-coding it to serviceOneMock, etc. modules.

AngularJS: one service several modules

This is a question about AngularJS modules and services, and how to define them.
An app can be composed of multiple modules
A service allows commonly-used code to be factored out and used by multiple modules
A service is (commonly) defined with:
angular.module('module1').factory('serviceA', function() { ... } );
If the above are all true, then why does the definition of serviceA include a reference to module1? Shouldn't it be ignorant of any modules that want to use it?
If I was building a module2 and I referenced serviceA.js in order to access the above service, it would tell me that module1 is not defined.
I guess my question is how do I create a set of independent modules and have them all access a global service? In all the examples I've seen the service is tightly-coupled to a specific module.
The factory() method is a method on module, so you need a module instance to be able to call it. Essentially, that statement says that you want that factory to be defined on that specific module.
If you need module1 in something used in module2, then module2 should declare a dependency on module1:
angular.module('module2', ['module1']);
One thing that writing unit tests will teach you really quickly is that the more places something is used, the more important it is to put it in a module. If you try to treat it as "global" because it's used in a lot of places, that means you have to bootstrap the entire app just to use those services that are basically used everywhere.

AngularJS $provider and $injector and bootstrapping

I've been trying to get into the nitty-gritty with angular DI and really the bootstrap process at large, and I am a bit confused as to where things really happen. In my mind, the events are in this order.
App starts.
$provider registers service providers.
In the config phase, the providers can be configured.
Now is where I am lost.
The $injector, now having access to all the configured providers from $provide, calls the constructor functions (the $get function in each provider) to instantiate service instances.
Also, if that process is correct, how does the $injector handle cases where a service depends on another service?
Services are only instantiated at the moment when they are needed, rather than during Angular's initiation. For example, if you have a controller that isn't activated yet and it depends on services which haven't yet been used, those services will be instantiated and injected whenever that controller becomes active (like changing to a view that uses it). From then on, the same instance of each service will be used.
The same is true of services that depend on other services. All dependencies of anything are resolved before it is instantiated, so if a dependency has dependencies, the same process is applied (all of that dependency's dependencies will be instantiated first, and so on).
If a circular dependency is found (service foo has a dependency that depends on service foo), Angular will throw an exception and the functionality of those services will have to be refactored into different services that will not have this kind of circular chain.

AngularJS: how angularjs executes?

I'm sure this is boring - it has bothered me for some time now.
I wonder how AngularJS executes?
AngularJS provides some basics Module's Service, Provider and Factory and functions like app.run() and app.config().
What is the executing order of these modules and functions?
If I want to execute a function before the controller or directive executes where should I place it?
AngularJS first gathers everything. Maybe you have written custom directives and filters and external components, AngularJS will first gather each and every resource. Then, it would try to satisfy all the mentioned and required dependencies. So, if your module depends on any external module then, angular would first, load the external module and then would pass it to dependent module.
Now, for app.run() and app.config () methods.
A function passed to app.run() will be executed when all the modules have been loaded. It means all the modules, including external ones.
And a function passed to app.config() will be executed when current module have been loaded.
If I were you, I would place the redirect code in config() method.

Don't understand the need for $cacheFactory if Factories are singletons

I'm relatively new to AngularJs and I'm trying to build a single page application with it. My application runs within a content management site. I have 3 factories for user, group and site functions.
I'm interested in using angular's $cacheFactory but I'm not sure what the benefit is if my data remains in the factory since it's a singleton.
For example, my user factory has an object called allUsers. This object is used through my application for different views. Intuitively, it seems like it's something that should be cached but I'm having a hard time understanding why since this object is in the user factory which can be access from any of my controllers.
CacheFactory is a factory:
The purpose of the Factory Method pattern is to define an interface for creating an object but deferring instantiation of the object to subclasses.
which creates new instances each time an object of its type is created, unlike a Singleton:
The intent of the Singleton pattern is to ensure that only one instance of a class is loaded, and that the instance provides a global point of access.
In Angular, the CacheFactory offers the following benefits over other solutions:
Caches can be injected into a filter, unlike controller scopes
Caches can be enumerated
Caches can be easily destroyed or redefined
Caches are not tied to digest data binding, unlike controller scopes
Caches are not tied to browser permissions, unlike cookies or localStorage/sessionStorage
I'm not sure what the benefit is if my data remains in the factory
CacheFactory offers the following features:
'should create cache with defined capacity'
'should blow away the entire cache via removeAll and start evicting when full'
'should correctly refresh and evict items if operations are chained'
But CacheFactory also has the following unexpected behaviors:
'should purge the next entry if the stalest one was removed'
'should only decrement size when an element is actually removed via remove'
References
Deep dive into JSF patterns
Factory method and MVC
AngularJS Source: cacheFactorySpec.js
Why is OOP Difficult?
DCOM and CORBA Side by Side, Step By Step, and Layer by Layer

Resources