I'm trying to work around the fact that I need to import a pure ESM package into a non-module. I can't change that fact about the script.
The workaround I'm trying to use is the import()
function (a "dynamic import"). That returns a Promise instead of the actual module. I can't use await
since I'm not in a module, so instead I'm using .then()
.
The pure ESM package (unist-util-visit) is used in a function exported by my script, which is then used in another script. So the import chain goes:
importer.js
imports imported.js
imports unist-util-visit
So the issue is that anything I export from within the .then()
function in imported.js
does not show up in importer.js
.
And it's not even a timing issue. I used an EventEmitter
to make importer.js
wait until imported.js
's .then()
is done executing:
imported.js
:
const EventEmitter = require('events');
module.exports.emitter = new EventEmitter();
module.exports.outsideFxn = function () {
console.log('hello');
}
import('unist-util-visit').then((unistUtilVisit) => {
module.exports.fxn = function() {
console.log(`unistUtilVisit: ${typeof unistUtilVisit}`);
}
module.exports.emitter.emit('ready');
});
importer.js
:
import('./imported.js').then((imported) => {
console.log("In importer.js's .then():");
console.log(' fxn:', imported.fxn);
console.log(' outsideFxn:', imported.outsideFxn);
imported.emitter.on('ready', () => {
console.log("After imported.js is done:")
console.log(' fxn:', imported.fxn);
});
});
When I execute it, this is the output:
$ node importer.js
In importer.js's .then():
fxn: undefined
outsideFxn: [Function (anonymous)]
After imported.js is done:
fxn: undefined
What am I missing? Why are no exports being defined in the .then()
function? How can I get my function exported?
Instead of
import('unist-util-visit').then((unistUtilVisit) => {
module.exports.fxn = function() {
console.log(`unistUtilVisit: ${typeof unistUtilVisit}`);
}
module.exports.emitter.emit('ready');
});
where you attempt to modify your module's exports
after it has probably been consumed by dependents, why not export a promise that yields the function when it completes?
module.exports.fxnP =
import('unist-util-visit')
.then((unistUtilVisit) => () => {
console.log(`unistUtilVisit: ${typeof unistUtilVisit}`);
});
Now you consume it:
import('./imported.js').then((imported) => {
imported.fxnP.then((fxn) => {
fxn();
});
});
or, more neatly::
import('./imported.js')
.then(({fxnP}) => fxnP)
.then((fxn) => fxn());