Problem
Recently when writing a project of mine, I've written some javascript like this:
import itemA from '../items/itemA';import itemB from '../items/itemB';import itemC from '../items/itemC';import itemD from '../items/itemD';
I'd really like some syntax like this:
for(const id of ['A','B','C','D']) {import (item+id) from '../items/item' + id;}
Turned out there's this
stage 4 proposal of ECMAScript
called dynamic import
that goes like:(async () => {await import('./my-app.mjs');})();
and it's supported by all modern browsers as well as node.
Failed Attempt
Then I went on writing some line code like this:
importedItems = await Promise.all(itemNames.map(async itemName => {try {const imported = await import(`../items/${itemName}`);logger.debug(`Imported item: ${itemName}`);return imported;} catch (err) {logger.warning(`Failed to import item: ${itemName}`);return null;}}));
But for later use of
importedItems
, a TypeError
has been raised stating that the importedItems
are actually type of Module
instead of expected item
. I tried manual type casting like this:return Item(imported);
But it didn't work and since it's not yet standardized feature (Due to be standardized in ECMAScript 2020), there's little information about it so I have to figure it out myself.
After a long time with
JSON.stringify()
and console.log
I finally figured it out.Solution
It should work like this:
return imported.default;
Full working snippet
importedItems = await Promise.all(itemNames.map(async itemName => {try {const imported = await import(`../items/${itemName}`);logger.debug(`Imported item: ${itemName}`);return imported.default;} catch (err) {logger.warning(`Failed to import item: ${itemName}`);return null;}}));
Reason
The reason is that when we use an
import
statement like this:import item from './itemA';
it automatically loads the
default export
of module 'itemA'
into the item
.But when we do expression like dynamic import like this:
(async () => {const item = await import('./itemA');})();
the item is a
Module
, by accessing Module.default
we are able to fetch its default export, same goes for any other exports.