-
Notifications
You must be signed in to change notification settings - Fork 159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce async support for getHandler #183
Conversation
6462567
to
ecb3051
Compare
462ca5e
to
5ba7c53
Compare
It would be great if @machty had a chance to review (though not a blocker per-se). |
|
||
return Promise.resolve(this.handlerPromise, this.promiseLabel("Start handler")) | ||
.then(function(handler) { | ||
return Promise.resolve(handler) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this nesting needed? I could be missing something, but I would think this would work:
return Promise.resolve(this.handlerPromise, this.promiseLabel("Start handler"))
.then(checkForAbort, null, self.promiseLabel("Check for abort"))
.then(beforeModel, null, self.promiseLabel("Before model"))
.then(checkForAbort, null, self.promiseLabel("Check if aborted during 'beforeModel' hook"))
.then(model, null, self.promiseLabel("Model"))
.then(checkForAbort, null, self.promiseLabel("Check if aborted in 'model' hook"))
.then(afterModel, null, self.promiseLabel("After model"))
.then(checkForAbort, null, self.promiseLabel("Check if aborted in 'afterModel' hook"))
.then(becomeResolved, null, self.promiseLabel("Become resolved"));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we can do that, the one issue with that approach (and the reason the code is this way) is if we have an error early on in the chain (for example when checking inaccessibleByURL
), then we have to propagate it through the whole chain which is annoying.
Determines if an object is Promise by checking if it is "thenable". | ||
**/ | ||
export function isPromise(obj) { | ||
return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you tweak to:
return ((typeof obj === 'object' && obj !== null) || typeof obj === 'function') && typeof obj.then === 'function';
We would prefer to only do the comparison to null
(instead of !!obj
) when it is an object
.
Just a few small nit-pick things, but this LGTM. Can you update those things and squash? |
Determines if an object is Promise by checking if it is "thenable". | ||
**/ | ||
export function isPromise(obj) { | ||
return ((typeof obj === 'object' && typeof obj !== null) || typeof obj === 'function') && typeof obj.then === 'function'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should just be obj !== null
, not typeof obj !== null
getHandler can now return a Promise for handlers that need to be fetched asynchronously. Two notable differences from the sync case are inaccessibleByURL and intermediateTransitionTo. inaccessibleByURL will now error after going through a loading state since we need to load the handler before being able to determine accessibility. intermediateTransitionTo will assume that the handler is available synchronously as it should be used for error and loading substates.
24c3164
to
02047bd
Compare
READY FOR REVIEW
In order to support lazy-loading, router.js should not assume handlers returned from
getHandler
will be present synchronously. This PR introduces support for loading handlers asynchronously by returning a Promise from thegetHandler
function.A common response to this idea is why not load handlers upfront? The reason to avoid loading handlers upfront is that they have the potential of being stateful and dependent on other constructs. This introduces a dependency tree that also must be loaded upfront with the handler, thus potentially negating the benefit of lazy loading.
This implementation reuses all existing tests that defined a
getHandler
method and has them passing while returning a Promise-based handler instead. One callout here is thatintermediateTransitionTo
passes under the assumption that it is used to transition into a synchronously loaded route.TODO: