如何从导入模块的 Promise 中导出?

How to export from within an imported module's Promise?

我正在尝试解决我需要导入 pure ESM package into a non-module. I can't change that fact about the script.

的问题

我尝试使用的解决方法是 import() 函数(“dynamic import”)。 returns 一个 Promise 而不是实际的模块。我不能使用 await 因为我不在模块中,所以我使用 .then().

纯 ESM 包 (unist-util-visit) 在我的脚本导出的函数中使用,然后在另一个脚本中使用。所以导入链是:

importer.js 进口 imported.js 进口 unist-util-visit

所以问题是我从 imported.js 中的 .then() 函数中导出的任何内容都没有显示在 importer.js.

而且这甚至不是时间问题。我使用 EventEmitterimporter.js 等到 imported.js.then() 完成执行:

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);
  });
});

当我执行它时,这是输出:

$ node importer.js 
In importer.js's .then():
  fxn: undefined
  outsideFxn: [Function (anonymous)]
After imported.js is done:
  fxn: undefined

我错过了什么?为什么 .then() 函数中没有定义导出?如何导出我的函数?

您可以使用像 jiti 这样的自定义 require 挂钩,它可以同步执行您想要的操作。

没有挂钩require:

$ node test.cjs

// test.cjs
const jiti = require('jiti')();
const unistUtilVisit = jiti("unist-util-visit");

以编程方式挂钩 require

$ node test.cjs

// test.cjs
require('jiti')().register();
const unistUtilVisit = require("unist-util-visit");

通过命令行选项挂钩 require

$ node -r jiti/register test.cjs

// test.cjs
const unistUtilVisit = require("unist-util-visit");

而不是

import('unist-util-visit').then((unistUtilVisit) => {
  module.exports.fxn = function() {
    console.log(`unistUtilVisit: ${typeof unistUtilVisit}`);
  }
  module.exports.emitter.emit('ready');
});

如果您尝试修改模块的 exports 之后它可能已被依赖项使用,为什么不导出一个在完成时产生函数的承诺?

module.exports.fxnP = 
    import('unist-util-visit')
      .then((unistUtilVisit) => () => { 
          console.log(`unistUtilVisit: ${typeof unistUtilVisit}`); 
      });

现在你消费它:

import('./imported.js').then((imported) => {
    imported.fxnP.then((fxn) => {
        fxn();
    });
});

或者,更简洁::

import('./imported.js')
    .then(({fxnP}) => fxnP)
    .then((fxn) => fxn());