【问题标题】:How to convert `require` to `import` within for loop?如何在for循环中将`require`转换为`import`?
【发布时间】:2022-11-17 09:23:42
【问题描述】:

以下是截取自:https://discordjs.guide/creating-your-bot/command-handling.html#loading-command-files 的 sn-p

client.commands = new Collection();

const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));

for (const file of commandFiles) {
    const filePath = path.join(commandsPath, file);
    const command = require(filePath);
    // Set a new item in the Collection with the key as the command name and the value as the exported module
    if ('data' in command && 'execute' in command) {
        client.commands.set(command.data.name, command);
    } else {
        console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
    }
}

在 for 循环中,我们通过执行 require(filePath) 来检索命令。如何使用导入实现等效行为?

大多数 Discord.js guide 使用 CommonJS,而我正在尝试使用 TypeScript 实现我的机器人。

【问题讨论】:

  • 简短的回答是这很难。也许不可能。在模块中 __dirnameundefined,动态导入是异步的,而 require 是同步的,等等。你可能可以在动态导入数组上使用Promise.all,然后运行命令,但我们需要了解更多关于您的用例的信息。坦率地说,我对 ES 模块的好处持怀疑态度,尤其是对于服务器端代码。
  • @JaredSmith 您可以通过采用new URL(import.meta.url).pathname 并删除文件名来模仿__dirname
  • @caTS 是的,虽然不得不做import { dirname } from path; const __dirname = dirname(import.meta.url); 或任何只是为了回到旧状态的事情很烦人。
  • 您可以使用导入功能并解决承诺import(path)

标签: typescript discord.js


【解决方案1】:

简短的回答是:不!require 函数在 typescript 中工作得很好,并且由于 typescript 将转换为 javascript,es6 语法纯粹是为了便于编写而不是性能优势。

更长的答案是:

导入对于模块、结构和许多其他事物可能很有用,但对于诸如 for 循环之类的迭代没有用,在这种情况下,您必须使用 import() 函数而不是 import 语句,它的工作方式与require() 函数除了其异步返回值之外,使 import() 函数完全多余。

这些被称为顶级导入与动态导入。您可以在this post 中阅读更多内容

虽然您不能使用 import 语句,但这并不意味着您的命令结构不能完全适应 es6 语法。例如,您可以使用 commonjs exports 更改您的命令结构:

module.exports = {
  commandData: new SlashCommandBuilder()...,
  async execute(...){
    ...
  }
}

对于像这样的 es6 出口:

export const commandData = new SlashCommandBuilder()...;
export async function execute(...){
  ...
}

这两个都可以使用 require 函数导入:

const { commandData, execute } = require('./command');

我希望这对您有所帮助,总而言之:仅仅因为选项在那里,并不意味着它是必要的。

【讨论】:

  • “它的工作原理与 require() 函数完全相同”,除了它不是。因为 require 是同步的:当你调用它时它返回 module.exports。动态imports返回一个承诺的事情。所以它甚至更差比您建议的要多,而且您对 OP 的建议更有必要,即他们不应该这样做。
  • 谢谢忘记了,更新的答案。
猜你喜欢
  • 2018-03-19
  • 2023-04-01
  • 2016-09-03
  • 2020-12-17
  • 1970-01-01
  • 1970-01-01
  • 2016-11-05
  • 1970-01-01
  • 2021-12-27
相关资源
最近更新 更多