Skip to content
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

Add Promise support to async route functions #3719

Merged
merged 7 commits into from
Aug 15, 2016
Merged

Add Promise support to async route functions #3719

merged 7 commits into from
Aug 15, 2016

Conversation

timdorr
Copy link
Member

@timdorr timdorr commented Aug 10, 2016

First pass at #3606. Not 100% happy with it right now. It would be easier to architect if we had guaranteed Promise availability, but alas...

I've got some practical things in there for Babel's default exports. And we can't just accept a Promise instead of a function, since System.import won't code split in that case. That's probably the most ugly part of it.

But this works:

<Route path='/' getComponent={() => System.import('./app')} />

@@ -0,0 +1,3 @@
export function isPromise(obj) {
return obj && typeof obj.then === 'function'
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dunno if this is worth throwing in a module. Maybe move it to AsyncUtils at least?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is okay for now I think.

// Try module.default first in case of System.import and Babel 6
.then(component => component.default || component)
.then(component => callback(null, component))
.catch(callback)
Copy link
Contributor

@taion taion Aug 10, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be

.then(
  component => callback(null, component),
  callback
)

We don't want to catch exceptions thrown in running the callback.

@taion
Copy link
Contributor

taion commented Aug 10, 2016

Super neat!

if (isPromise(componentReturn))
componentReturn
// Try module.default first in case of System.import and Babel 6
.then(component => component.default || component)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's Babel 6 – I think that's just what System.import does, no? What happens if there are non-default exports.

I wonder if we should handle this though. Presumably users can do

function asyncComponent(id) {
  return System.import(id).then(component => component.default);
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't followed the spec discussions closely enough to know what the standard implementation will do. But since Babel is the only way to consume exports at the moment, it's realistically how things are going to be for the next few years (at least). So this is more of a practical enhancement to be a little more friendly to users.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like that should live in user space though. We don't have anything like this in the callback-based path. I do agree that this is friendlier, but I think philosophically it's not right here.

Also, webpack 2 can handle these things natively now... users on webpack 2 actually are using that native ES module support now that we have the module entry point.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(but the API for them looks the same)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other thing is that the spec doesn't really define how System.import works. Probably you'd using it with webpack 2, which takes a guess, but isn't actually going through Babel. It might make a lot of sense to change this down the road, but I think we should at least see how it plays initially in the simpler form, and reserve room to change up how it works as the spec for System.import comes into existence.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, not a huge deal to me, so I dropped them. But you get the blame if users complain :P

@timdorr
Copy link
Member Author

timdorr commented Aug 10, 2016

Browser Stack wigged out again. Build is passing now.

@timdorr
Copy link
Member Author

timdorr commented Aug 15, 2016

So are we yay or nay?

@taion
Copy link
Contributor

taion commented Aug 15, 2016

Looks great! :shipit:

@timdorr timdorr merged commit ec523e4 into next Aug 15, 2016
@timdorr timdorr deleted the promissory-note branch August 15, 2016 02:23
@taion
Copy link
Contributor

taion commented Aug 15, 2016

Thanks! 🎉

I'll cut another alpha once we figure out if we want #3717.

@oscar-b
Copy link

oscar-b commented Sep 28, 2016

Since 1ebbf58 the initial example isn't valid any more, you probably need to do this:

    <Route path='/' getComponent={() => System.import('./app').then(poo => poo.default)} />

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants