2

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.

1 Answers1

2

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

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265