简体   繁体   English

ESM/节点的正确导入/导出和绑定

[英]proper import/export and binding for ESM/Node

I have some pre-ES6 code that was working fine with require-type syntax, and am trying to port this to ESM friendly methodology.我有一些 ES6 之前的代码可以很好地使用 require 类型的语法,并且正在尝试将其移植到 ESM 友好的方法中。 I have much of the js to mjs coding ported, and am working on a dynamic file loading block, that is giving me fits.我已经移植了很多 js 到 mjs 编码,并且正在处理动态文件加载块,这让我很合适。 I've gotten through enough googling and debugging to realize my issue is now with the syntax of the export function in the "events" file, which I'm using default syntax to support.我已经通过足够的谷歌搜索和调试来意识到我的问题现在是“事件”文件中导出函数的语法,我使用默认语法来支持。

First the calling file:首先是调用文件:

async function eventLoad(eventDir = './events/')
    {
        await fs.readdir(`./events/`,function (err, files){
            if (err)
            {
                console.error(`${error}: Error loading event: ${err}`);
                return;
            }
            else
            {
                const events = files.filter(file=>file.endsWith('.mjs'));
                for( const file of events)
                {
                    console.log(`event file name is ${file}`);
                    const {default: event} = import(join(`./events/`,`${file}`));
                    const eventName = file.split('.')[0];
                    dBot.on(eventName, event.bind(null,dBot));
                    console.log(`${success} Loaded event ${eventName}`);
                }
            }
        })
    }
    eventLoad();
// please ignore the missing promise on the import...I'll be adding it shortly. :)

I get an error: TypeError: Cannot read property 'bind' of undefined我收到一个错误:类型错误:无法读取未定义的属性“绑定”

my export in the other file declares like this:我在另一个文件中的导出声明如下:

export default async (client, message) =>
{
...

knowing from googled issues that much of the likelihood rests in the improper definition in the file that is exporting the fuction, I tried playing with the syntax:从 googled 问题中知道大部分可能性在于导出功能的文件中的不正确定义,我尝试使用语法:

async function ProcessMessages (client, message)
{
...
}
export {ProcessMessages as default };

but alas, no help.但唉,没有帮助。 I'm sure the issue is properly handling the export syntax, but I'm learning this as I go, and would appreciate any help you could provide, thanks!!!我确定问题是正确处理导出语法,但我正在学习这一点,并希望您能提供任何帮助,谢谢!!!

Update: (based on solution, here is my code changes in case anyone else wants to leverage)更新:(基于解决方案,这里是我的代码更改,以防其他人想要利用)

async function eventLoad(eventDir = './events/')
{
    let files;
    try {
        files = await promiseBasedReaddir(`${eventDir}`);
    }
    catch (err) {
        console.error(`${error}: Error loading event: ${err}`);
        return;
    }
    const events = files.filter(file=>file.endsWith('.mjs'));
    for( const file of events)
    {
        console.log(`event file name is ${file}`);
        import(`${eventDir}${file}`)
        .then(function( {default: event} ){
            const eventName = file.split('.')[0];
            dBot.on(eventName, event.bind(null,dBot));
            console.log(`${success} Loaded event ${eventName}`);
        })
        .catch(function(err){
            console.error(`${error}: Error loading event: ${err}`);
            return;
        })

    }
}
eventLoad();

On this line, you do a dynamic import:在这一行,您执行动态导入:

const {default: event} = import(join(`./events/`,`${file}`));

import will always return a Promise. import将始终返回一个 Promise。 The Promise object doesn't have a .bind method, only functions do. Promise 对象没有.bind方法,只有函数有。 You need to await or .then() import() 's return value.您需要await.then() import()的返回值。 So you can't "ignore the missing promise on the import".所以你不能“忽略导入时丢失的承诺”。

A second issue:第二个问题:

 await fs.readdir(`./events/`, ...´

fs.readdir doesn't return a promise, so await -ing it is useless. fs.readdir不返回承诺,所以await -ing 它是无用的。 It is functionally the same as await undefined;它在功能上与await undefined;相同await undefined; . . The outer function will return before the callback has finished.外部函数将在回调完成之前返回。

If you use a readdir function that returns a promise, you can simplify things a lot.如果您使用返回承诺的readdir函数,您可以简化很多事情。

    import { promises as fsPromises } from 'fs';
    const { readdir: promiseBasedReaddir } = fsPromises;

    // OR alternatively:
    import { readdir } from 'fs';
    import { promisify} from 'util';
    const promiseBasedReaddir = promisify(readdir);

    async function eventLoad(eventDir = './events/')
    {
        let files;
        try {
            files = await promiseBasedReaddir(`./events/`);
        } catch (err) {
            console.error(`${error}: Error loading event: ${err}`);
            return;
        }
        
        const events = files.filter(file=>file.endsWith('.mjs'));
        for( const file of events)
        {
            console.log(`event file name is ${file}`);
            const {default: event} = await import(join(`./events/`,`${file}`));
            const eventName = file.split('.')[0];
            dBot.on(eventName, event.bind(null,dBot));
            console.log(`${success} Loaded event ${eventName}`);
        }
    }

Promisify will transform a callback-using function to a promise-returning function. Promisify会将使用回调的函数转换为返回承诺的函数。 The fs module has promise-based functions, so you don't need to use Promisify if you just import those. fs模块具有基于 promise 的函数,因此如果您只导入这些函数,则不需要使用 Promisify。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM