Asynchronous Module Initialize

Jussi Kalliokoski jussi.kalliokoski at
Wed Jul 9 13:57:21 PDT 2014

On the ModuleImport thread, I pretty much derailed [1] the conversation
with poor argumentation which lead to the discussion drying out. But the
more I think about it, the more important I feel my concern was so I
figured I'd have another shot at it.

The problem I was describing is that, as with any problem space complex
enough, there is a conflict of interest between different sets of use
cases. As Brendan replied [2] to my post, the goals of the current design
of the module system include:

* Static vs. dynamic imports and exports. This enables read-time import
resolving, better (or at least easier to build) tooling, import:export
mismatches as early errors, leaves the door open for static metaprogramming
patterns like macros and types and probably other benefits. Also the
transitive cyclic dependencies I unwarrantedly focused on.
* Paving the cowpaths of existing patterns, such as named exports and
default exports.

Like I stated in the other thread, I'm a big fan of the static imports and
the read-time import resolving that it brings to the table. However, the
use case incompatibilities arise from the static exports side of things. I
proposed (it was less of a proposal though, more an idea or an example to
spur better ideas) that we had a single dynamic exportable per each module,
and that could be an object, function, undefined for side effects or
anything. But, the important part was that it could also be a Promise of
what you want to export, allowing asynchronous module initialization.

The use cases addressed include:

* Optional dependencies (required for porting large amounts of existing
code to use ES6 modules).
* Async feature detection.
* Dependencies on things other than JS, such as stylesheets, images,
templates or configuration (e.g. a default language pack).
* Waiting on something to be ready, for example something like jQuery could
wait for DOM ready so that the API consumer doesn't have to.

All of these can be done with the current design, however you cannot defer
the module being ready to be imported. So if you depend on these use cases,
you have to provide async APIs for things that are possibly synchronous
otherwise, not only imposing a performance penalty, but also a convenience
downer on the consumers of your API.

I'm quite skeptic of this being possible to retrofit to the current design
without sacrificing static exports, but I'd be more than happy to see
myself proven wrong and we have a lot of smart minds gathered here so

I really like macros (all good things in moderation of course) and sweet.js
and use it occasionally even for production code. Before that I sometimes
even used GCC's preprocessor to get macros in JS. I also really like types
- in moderation as well, i.e. declaring the types of inputs and outputs of
functions. This is to say, I'm definitely not just happily trying to close
the metaprogramming door here. But I think things like macros and types are
something that can be done and is being done with tooling, at least to some
extent, whereas optional dependencies for example, not really, at least my
imagination is too limited to see how.

Of course, the ES6 modules ship is already overdue, there's already tooling
made for it and probably browsers are prototyping the current design as
well, so maybe these use cases are something we don't want to or can't
(anymore) afford to consider. Or maybe they are less important than the use
cases that would be excluded if we included async module initializing. And
that's all fine, as long as it's a conscious choice made with these
implications considered. (Maybe not personally fine for me, but I've
survived with the status quo so I can probably survive with using the
existing solutions if I have a use case that's not elegantly solved by ES6

[2] For some reason, I could not find the reply on
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list