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

It should be possible to synchronous retrieve a "loaded and ready" module's export object #130

Open
concavelenz opened this issue Feb 25, 2016 · 7 comments
Labels

Comments

@concavelenz
Copy link

I'm basically looking for a "retrieve X if present" without initiating a load.

In order to lookup a module from the registry, the "key" must be obtained, the "key" is only available via the "resolve" method (the key is loader defined so unpredictable), and the resolve method returns a promise which will never provide a value synchronously.

@concavelenz
Copy link
Author

I have two use cases for this:
(1) conditionally use code if it is present.
(2) make ES6 modules available to traditional scripts by delaying the loading of those script until after the known ES6 module dependencies are available, and then allow the script to retrieve the module synchronously as they are loaded and evaluated.

@caridy
Copy link
Contributor

caridy commented Feb 27, 2016

(1) conditionally use code if it is present.

Are you talking about polyfills by any chance? Who is responsible for importing the code in the first place?

(2) make ES6 modules available to traditional scripts by delaying the loading of those script until after the known ES6 module dependencies are available, and then allow the script to retrieve the module synchronously as they are loaded and evaluated.

Interesting. In this scenario I suspect you will need a master puppet that will import the modules, wait for them to be ready, and then evaluate the script. Similar scenario happens today with modules compiled with browserify/webpack, and somehow, the communication between the two pieces running a different modes (async vs sync) happens via some global variable or function. Still, you should be able to do:

let mod = System.loader.registry.get('a-module-key').module; // flaky
mod.foo('do something');

My argument here is: if your script is already using the loader, and knows the key of the module, why not just use the import() mechanism? If the issue is not having to rely on an async process because of the ergonomics of the code, top level await my help:

let mod = await System.loader.import('my-module'); // robust
mod.foo('do something');

@concavelenz
Copy link
Author

No, not polyfills, think a optional logging library or some such thing.

@concavelenz
Copy link
Author

I should be specific about what my original motivation is here: I am trying to build a bridge between current module systems and ES6 modules. My goals were:

  • allow gradual transition of code to ES6 modules
  • don't invent new syntax/library
  • avoid code translations ("transpilation, etc")

My general line of approach was this:

  • preload all ES6 modules (I want to do this anyway to avoid cascading network requests).
  • force all needed ES6 module to be evaluated
  • when they are ready, start loading the scripts that depend on the ES6 modules

And what I was looking for was the syntax to synchronous access the "load and ready" scripts: except there isn't any. What I was expecting was something like:

   var foo = System.loader.getModuleIfPresent('./foo'); // or similar method

Such a system would need to gather needed dependencies server-side but would not need to modify any of the files. However, no such API exists. System.loader.registry.get is close but it needs a key something the code author does not have (as the value is left to the loader, it is impossible to predict). So I left with poor choices:

  • invent my own loading library API that allows for synchronous location resolution
  • force all code to be migrated to ES6 module (impossible)
  • don't migration to ES6 modules (unfortunate)
  • do automated translation of the legacy scripts

It isn't at all clear what the use case a async "resolve" step is trying to support.

@caridy
Copy link
Contributor

caridy commented Feb 29, 2016

I will discuss the use-case with other folks in upcoming weeks, but for me, it smells. Think about how do you do this today with scripts only? And work your way back from that.

If your scripts can't use the loader (it seems), then create your own global registry from where they can get what they need, e.g.:

var legacyRegistry = {}; // this could be `window` as well.
System.loader.import('foo').then((mod) => {
     legacyRegistry['<whateverIdentifierAre>'] = mod;
}).then(() => {
     // load scripts that will rely on `legacyRegistry`
});

@concavelenz
Copy link
Author

Right, there I have to (a) a new API to use the legacyRegistry (b) create a means of resolving the relative paths used in the script. I want to avoid (a) and in the general case (b) isn't currently possible as the "name" of the script isn't known.

@concavelenz
Copy link
Author

Is there any update on this? I'm still haven't seen any proposal to solve circular imports in a meaningful way. "import(...).then(...)" has the wrong timing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

2 participants