dynamic synchronous import

# Konstantin Ikonnikov (11 years ago)

Can I import module dynamically, but synchronously? Example for common js

var moduleName = 'foo';
var foo = require(moduleName);

In es6 draft I found that ModuleSpecifier must be a StringLiteral people.mozilla.org/~jorendorff/es6-draft.html#sec

# John Barton (11 years ago)

no.

# Marius Gundersen (11 years ago)

And the reason you cannot import a module synchronously is that it would freeze the entire browser until the http request completes, which could be several seconds on a slow internet connection.

If you want to import something dynamically you can do it using the API (to be finalized, I believe):

var moduleName = 'foo';
Loader.import(moduleName).then(function(foo){
  //use foo here
});
# Brendan Eich (11 years ago)

Konstantin Ikonnikov wrote:

Can I import module dynamically, but synchronously? Example for common js

var moduleName = 'foo';
var foo = require(moduleName);

You can't do that in the browser, as followups point out. Do you use browserify or similar to make this seem to work? If so, that's not dynamic-synch.

# Konstantin Ikonnikov (11 years ago)

I don't want load module using http request. In my case module already defined and I want import it later when I get its name:

var moduleName = getModuleName();
import { foo } from moduleName;

// use foo
# Calvin Metcalf (11 years ago)
var moduleName = 'foo';
var foo = require(moduleName);

would not work in browserify either

# Bradley Meck (11 years ago)

It does work in browserify, but you need to be sure to include it in a list of requires if it is not imported by the current list of files statically (ala browserify -e main.js -r foo).

# Calvin Metcalf (11 years ago)

true and by that same token it is possible to use the loader api to get similar results out of ES6 modules (calvinmetcalf/es6-translate)

# John Barton (11 years ago)

Theoretically you can use System.normalize() and System.get() to lookup a module by name synchronously. The normalize feature requires a referrer or address.

Since browsers are determined to eliminate synchronous scripts, you may as well deal with the asynchronous System.import() and obnoxious promises stuff now and save yourself some pain later.

# John Lenz (11 years ago)

I would like to see some way to preload everything, and be able to retrieve them synchronously, something like:

System.loader.addNoAsync('...');  // throw if all imports aren't available already

So that the script could be used during initial render. I understand that this would mean that the module would need to be parsed and executed synchronously. Forcing folks to never use any module for code that needs to be inline seems like a bad turn.

# Domenic Denicola (11 years ago)

From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of John Lenz

I would like to see some way to preload everything, and be able to retrieve them synchronously, something like:

Sounds like a good custom loader extension that you could write.

# Sam Tobin-Hochstadt (11 years ago)

Note that of all you want is to load of it's already available, and fail otherwise, that's already provided. If what you want is sync io though, tc39 is not going to add it.

# Jasper St. Pierre (11 years ago)

I'm confused. We went from bundled, synchronous modules to asynchronous modules... Why exactly?

And what about the offline case where modules are loaded from disk or are even complied into an archive file (for fast seek times on rotating disks)? Are those use cases not important to TC39?

Does the loader API handle all resources? Can I load other assets like images with it? Can I have one simple preloader for my game which says map_3 depends on these assets/modules/level scripts, and have ES6 take care of the rest?

# Guy Bedford (11 years ago)

On 28 September 2014 07:01, John Lenz <concavelenz at gmail.com> wrote:

I would like to see some way to preload everything, and be able to retrieve them synchronously, something like:

System.loader.addNoAsync('...'); // throw if all imports aren't available already

So that the script could be used during initial render. I understand that this would mean that the module would need to be parsed and executed synchronously. Forcing folks to never use any module for code that needs to be inline seems like a bad turn.

I'm not sure what rendering behaviour is planned for <script type="module">, but I hope there would be a way to indicate when it should and shouldn't block rendering of the HTML page / HTML import.

In terms of preloading, there are complete ways to do this through custom extensions.

# Matthew Robb (11 years ago)

Also you CAN potentially do something like this eventually:

(async function() {
    var myMod = await System.import("my-mod");
})()
# John Barton (11 years ago)

What is wrong with Loader.get()?

Reflect.Loader.prototype.get ( name )

If this Loader's module registry contains a Module with the given normalized name, return it. Otherwise, return undefined. If the module is in the registry but has never been evaluated, first synchronously evaluate the bodies of the module and any dependencies that have not evaluated yet.

But more important perhaps, what is wrong with asynchronous loads? The System.import() promises a module after loading all of its dependencies; previously imported modules are not reloaded. This code can be used in development, then in production the bundled modules can be prefixed to load the registry and the same call executes the same app. If this scheme is not going to work now is the time to sort it out.

# Katelyn Gadd (11 years ago)

What is wrong with asynchronous loads other than the fact that they can't be used in synchronous algorithms, you mean? (i.e. the vast majority of existing software)

That seems to be the motive: Not synchronous network or disk i/o, just synchronous import. I can see how there's perhaps a moral argument to be made about why that shouldn't be possible.

I guess if you use the loader api to synchronously fetch an existing module, all you have to do is manually implement the 'import' part yourself by pulling names out of it and into the current namespace.