Module start might be asycnchronous
Each module has an initing phase, and the phase might be asynchoronous because you want to do something asynchronously. For example, a module may need to read some configuration from db to set up the environment; we will say this module is not ready yet if it's still in the init phase.
Service is playing the role of message queuing between modules
We call this 'Durable subscriber' in the messaging pattern.
That is, event dispatching will be lost if the subscriber is not ready when the dispatcher loads before the subscriber. To avoid this, we need a third module to queue the request of the dispatcher before the subscriber is able to register to the requests.
How to know the application is fully loaded if we decide to delay something?
A rough idea here is let every module to notify the centralized controller when it starts.
But this does not make sense because we need to maintain a list of all the modules in the centralized controller.
A promise chain of start operations
A module may have some sub modules to load and start in the init phase. If we connect all the start function using Promise, we could have a simple start function call from the application root and simply knows when all the sub modules are started.
Tricky: Define critical modules and side modules but keep the start promise
For reason of performance we don't want everything to be loaded together in startup. That is to say, we need to figure out what's the critical module and what's the side modules.
loadWhenIdle function call will not being resolved once the consumer of 'schedule' Service tell it now is time to do your operation. So now we need a new module to schedule the non critical operations. It should know the timing that all critical modules are loaded and started, and then execute the queued requests.