App.initializer
name: "first"
initialize: (container) ->
$.get('/api/connect').then (data)
# do some work
App.initializer
name: "second"
after: "first"
initialize: (container) ->
# do something that requires result of first initializer
As it currently stands the initializers will run in the correct order, but the second initializer will (potentially) run before the ajax callback has completed. If you have an asynchronous initializer that should block boot you can use deferReadiness, but for the above case that won’t work, you need to combine the two initializers into one (I believe).
My proposal is that initializers should respect promises, and only execute the next initializer if initialize returns null and/or a resolved promise.
it will absolutely run the 2nd initializer, and all initializers before any of the ajax callbacks complete. As the initializers graph is walked synchronously, and promises always resolve on the next turn. So no scenario may exist in-which this is not true.
I believe that we have two great tools (promises, and initializers) which can, if needed, work well together. Combining them will likely just be a negative complexity increase.
Initializers are ordered based on how their DAG is described, and promise resolutions are ordered based on how the promise graph is described, in conjunction with the order resolutions occur. This provides us with tooling to resolve the sync configuration ordering, and tooling to resolve asynchronous dependencies.
In the scenario were you must have multiple initializations that share some or depend on some state, if that state is asynchronous in nature, the references to this state should be promises. Then given that all async state references are modeled as promises, when the initializers are walked they each build up the async deps. Once the initializers are all traversed the promise graph asynchronously resolves itself. Additionally if app boot needs to be synchronized advance/defer readiness can be used.
That all makes sense. I was thinking that maybe the results of the initializers could be linked in the order that they are currently processed, so that they will be run asynchronously, but in the correct order (if that makes sense?). However, I agree that it’s probably negative complexity, and you can stash the dependencies between the promises globally and do it that way, which achieves the same thing.
@stefan what do you about using ApplicationRoute#model hook to call execute async code? As far as I’m aware, you would rarely ever actually use ApplicationRoute#model, but it seems to be a good place load data that you need to run the app. I’m writing some code that looks like this
the router is likely one of the best places to load async code. That being said, our current loading state solution is sub-optimal, and will be getting some more attention shortly.