NodeJS 将import()转换为同步

qgelzfjb  于 2023-02-08  发布在  Node.js
关注(0)|答案(7)|浏览(344)

我试图把我所有的节点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()

z9gpfhce

z9gpfhce1#

目前commonJS无法做到这一点,除非有同步的import()或顶层等待,否则无法做到这一点。

mv1qrgav

mv1qrgav2#

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

vxbzzdmp

vxbzzdmp3#

当前版本的Node.js支持在标志--harmony-top-level-await(Node〉= 13.2)或--experimental-top-level-await(Node〉= 14.3)后面的顶级等待。

import fs from 'fs';

可以在CommonJS中重写为

const fs = await import('fs');
dldeef67

dldeef674#

您可以使用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();

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

llew8vvj

llew8vvj5#

我在nodejs文档中发现了以下内容:

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

// sibling-module.js is a CommonJS module.
const siblingModule = require('./sibling-module');

这允许您在es6+中重新创建“require”函数,我没有测试它是否工作,但文档说可以👍
图片来源:https://nodejs.org/docs/latest-v15.x/api/module.html#module_module_createrequire_filename

bsxbgnwa

bsxbgnwa6#

如果要调用await import(...)以获得路径列表,可以使用Array.reduce()并将Promise作为初始值。
这将允许您同步迭代内部调用await import()的承诺列表,如下所示:

const paths = fs.readdirSync(...);

const classes = await paths.reduce(async (acc, path) => {
    const arr = await acc; // This waits for the previous iteration to resolve.
    const mod = await import(path + '/somefile.js');
    arr.push(mod.default);
    return arr;
}, Promise.resolve([])); // Start with an immediately resolved promise

自节点v14.8 https://nodejs.org/en/blog/release/v14.8.0/起提供顶级await

iq0todco

iq0todco7#

在这个github问题中有一些关于它的评论-https://github.com/nodejs/modules/issues/454基本上是在做一个esm模块的需求。
deasync之外,使用黑客作为变通方案。
还有synckit,尽管它要求传递的数据可以通过Structured clone算法序列化

相关问题