【问题标题】:How to export from within an imported module's Promise?如何从导入模块的 Promise 中导出?
【发布时间】:2021-09-22 22:54:00
【问题描述】:

我正在尝试解决我需要将pure ESM package 导入非模块的事实。我无法改变关于the script 的事实。

我尝试使用的解决方法是import() 函数(“dynamic import”)。这将返回一个 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() 函数中没有定义导出?如何导出我的函数?

【问题讨论】:

    标签: javascript node.js es6-promise es6-modules


    【解决方案1】:

    代替

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

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

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

    【讨论】:

    • 哇,谢谢!它有效,但我不确定为什么。我真的需要更好地处理 Promises。
    【解决方案2】:

    您可以使用自定义的 require 钩子,例如 jiti,它可以同步执行您想要的操作。

    不钩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");
    

    【讨论】:

    • 哇,这太棒了。所以看起来它转换了导入的模块及其依赖项以将它们转换为 CommonJS?这有什么兼容性问题吗?
    • 我不知道,一切都应该正常工作!这是直接翻译。
    • 好的,我发现了我的第一个不兼容问题!我的模块默认导出了一个函数,当jiti 导入它时,结果不是函数,而是一个对象,其default 键是函数。
    • 不,这是出于兼容性原因的预期行为。如果它不这样做,我会认为它是一个错误。看到这个答案:stackoverflow.com/a/40295288/12375929
    猜你喜欢
    • 2019-10-27
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    • 2017-12-31
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    相关资源
    最近更新 更多