Asynchronous Module Initialize

Jussi Kalliokoski jussi.kalliokoski at gmail.com
Thu Jul 10 11:11:39 PDT 2014


On Thu, Jul 10, 2014 at 6:40 PM, John Barton <johnjbarton at google.com> wrote:

>
> On Wed, Jul 9, 2014 at 1:57 PM, Jussi Kalliokoski <
> jussi.kalliokoski at gmail.com> wrote:
> ...
>
>>  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.
>>
> ...
>
> If I understand your question here, I think the current solution as
> adequate support for these cases.
>
> The current module loading solution mixes imperative and declarative
> specification of the JS execution order. It's a bit of a layer cake:
> imperative layer trigger declarative layers trigger imperative layers.
>
> The top imperative layer (eg System.import()) loads the root of the first
> dependency tree and parses it, entering a declarative specification layer,
> the import declarations. These declarations are then processed with Loader
> callbacks, in effect more imperative code, that can result in parsing and
> more declarative analysis.
>
> By design the declarative layers prevent all of the things you seek. This
> layer is synchronous, unconditional, wired to JS exclusively.
>
> The imperative layers support all of the use cases you outline, though to
> be sure some of this is more by benign neglect than design.
>
> By providing a custom Loader one can configure the module registry to
> contain optional, feature-detected modules or non-JS code. The Loader can
> also delay loading modules until some condition is fulfilled.   I expect
> that multiple custom loaders will emerge optimized for different use cases,
> with their own configuration settings to make the process simpler for devs.
>  Guy Bedford's systemjs already supports bundling for example.
>

Interesting, thank you! I like this in the sense that the goal seems to not
be the ultimate solution, but the tool for building one (or many). So, do
you have any examples of how having optional dependencies would look from
the API providers' perspective, versus e.g. the examples I showed earlier:

// foo.js
export System.import("optional-better-foo-implementation")
  .catch( => System.import("worse-but-always-there-foo-implementation") );

Does the provided by the custom loaders defer the responsibility of taking
care of the optional dependencies to the API consumer, e.g. by dictating
which module loader to use for loading the module at hand? That might not
be ideal, especially if your code base is built on features of one loader
and then want to employ a third party library that is built on the
assumption of another loader. But maybe the future will show it to be a
worthy compromise.

- Jussi


> This approach concentrates the configuration activity in the code
> preceding the load of a dependency tree (and hopefully immediately before
> it). This seems like a better design than say commonjs where any module at
> any level can manipulate the configuration.
>
> The only unfortunate issue in this result is the decision to embed the
> custom loader in the global environment. This means that a tree of
> interdependent modules can issue Loader calls expecting a particular Loader
> to be in System so a custom loader will have to set/unset the global while
> loading the tree. Maybe we can experiment with modular loaders some time.
>
>
> jjb
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140710/127433c7/attachment-0001.html>


More information about the es-discuss mailing list