我试图把我所有的节点require()
转换成import()
语句,然而,那些是异步的,我遇到了一点麻烦。
现在我有:
import * as fs from 'fs';
const paths = fs.readdirSync('./src/modules').map(path => './modules/' + path.slice(0, path.length - 3));
const classes = [];
paths.forEach(path => {
let bClass = require(path);
try {
classes.push(new bClass.default());
}
catch (err) {
//Here for if no default import
}
});
并且希望将require(path)
部分转换为import()
,但仍希望保持同步,这可能吗?如果可能,我将如何实现它?
编辑:多一点上下文。我有一个我们想要导入的模块列表,我们这样做,所以如果一个模块出了问题,我们可以注解掉/删除它,而不必重新编码其他的东西。我只需要动态同步导入,而不使用require()
。
7条答案
按热度按时间z9gpfhce1#
目前commonJS无法做到这一点,除非有同步的
import()
或顶层等待,否则无法做到这一点。mv1qrgav2#
您仍然可以使用require()函数通过使用这个babel插件https://www.npmjs.com/package/babel-plugin-dynamic-import-node-sync
vxbzzdmp3#
当前版本的Node.js支持在标志
--harmony-top-level-await
(Node〉= 13.2)或--experimental-top-level-await
(Node〉= 14.3)后面的顶级等待。可以在CommonJS中重写为
dldeef674#
您可以使用deasync或node-sync将任何内容(包括导入)转换为同步,而不会阻塞整个节点进程。
下面是我编写的一个插件:require-esm-in-cjs
或者你可以阻塞整个过程,然后使用
require('child_process').execSync
加载包。通常不推荐这样做,但是对于编译本地脚本等来说可能是可以的。此外,CommonJS支持函数内的async/await。所以在很多情况下你可以这样做(这是异步的,但是有同步的函数流)
而且,如果您使用的是ESM模块,现在支持顶级await()。
llew8vvj5#
我在nodejs文档中发现了以下内容:
这允许您在es6+中重新创建“require”函数,我没有测试它是否工作,但文档说可以👍
图片来源:https://nodejs.org/docs/latest-v15.x/api/module.html#module_module_createrequire_filename
bsxbgnwa6#
如果要调用
await import(...)
以获得路径列表,可以使用Array.reduce()
并将Promise
作为初始值。这将允许您同步迭代内部调用
await import()
的承诺列表,如下所示:自节点v14.8 https://nodejs.org/en/blog/release/v14.8.0/起提供顶级
await
iq0todco7#
在这个github问题中有一些关于它的评论-https://github.com/nodejs/modules/issues/454基本上是在做一个esm模块的需求。
deasync之外,使用黑客作为变通方案。
还有synckit,尽管它要求传递的数据可以通过Structured clone算法序列化