将 import() 转换为同步

R. *_*lie 15 javascript node.js typescript

我正在尝试将所有 noderequire()转换为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
    }
});
Run Code Online (Sandbox Code Playgroud)

并希望将该require(path)部分转换为一个import()但仍希望保持同步,这可能吗?如果是,我会怎么处理?

编辑:多一点上下文。我有一个我们想要导入的模块列表,我们正在这样做,所以如果某个模块出现问题,我们可以将其注释掉/删除它,而不必重新编码其他所有内容。我只需要动态同步导入而不使用require().

小智 13

我在nodejs文档中找到了这个:

import { createRequire } from 'module';
const require = createRequire(import.meta.url);

// sibling-module.js is a CommonJS module.
const siblingModule = require('./sibling-module');
Run Code Online (Sandbox Code Playgroud)

这允许您在 es6+ 中重新创建“require”函数,我还没有测试它是否有效,但文档是这样说的

来源: https ://nodejs.org/docs/latest-v15.x/api/module.html#module_module_createrequire_filename


R. *_*lie 11

目前没有办法用 commonJS 做到这一点。在有一些同步import()或顶级等待之前,这是无法完成的。


Sam*_*ody 9

您可以使用deasyncnode-sync将任何内容(包括导入)转换为同步 - 而不阻塞整个节点进程。

这是我为此编写的一个插件: require-esm-in-cjs

或者您可以阻止整个过程并使用加载包require('child_process').execSync。通常不建议这样做,但对于编译本地脚本等可能没问题。

此外,CommonJS 支持函数内的 async/await。所以在很多情况下你可以这样做(这是异步的,但具有同步功能流程)

async function main(){
    let mod = await import('my-module')
        .catch(console.log);
    // do something with mod...
    }
main();
Run Code Online (Sandbox Code Playgroud)

而且,如果您使用 ESM 模块,现在支持顶级 wait()。


GOT*_*O 0 6

--harmony-top-level-await当前版本的 Node.js 支持标记(Node >= 13.2) 或--experimental-top-level-await(Node >= 14.3)后面的顶级等待。当使用任一标志启动 Node 时,像这样的导入

import fs from 'fs';
Run Code Online (Sandbox Code Playgroud)

可以用 CommonJS 重写为

const fs = await import('fs');
Run Code Online (Sandbox Code Playgroud)


小智 5

您仍然可以通过使用这个 babel 插件https://www.npmjs.com/package/babel-plugin-dynamic-import-node-sync来使用 require() 函数