You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS使用sqlite3模块时await无法等待.get()查询结果问题

问题根源

sqlite3 原生提供的是回调风格API,这类API不会返回Promise对象,而await关键字仅对Promise/符合Promise A+规范的thenable对象生效,因此你直接在.get()调用前加await不会等待查询执行完成。代码会直接向下运行,此时查询完成的回调还没触发,prefix变量未被赋值,自然返回undefined。

额外提醒:你当前直接拼接message.guild.id到SQL语句的写法存在SQL注入风险,即便是Discord的雪花ID,也建议统一用参数化查询传参。另外你把机器人消息判断放在了查询之后,会产生大量无意义的数据库请求,浪费性能。

修复方法

方法1:手动包装为Promise(兼容所有sqlite3版本)

将查询逻辑包裹在Promise中,在回调内部处理查询成功/失败的状态,即可正常使用await等待结果返回,修复后的完整代码如下:

module.exports = {
  name: "messageCreate",
  once: false,
  async execute(client, message) {
    // 提前拦截机器人消息,减少不必要的数据库查询
    if (message.author.bot) return;

    // 包装查询为Promise
    const prefix = await new Promise((resolve, reject) => {
      client.db.get(
        // 用?做参数占位符,走参数化查询
        `SELECT prefix FROM "Guilds" WHERE id = ?`,
        [message.guild.id],
        (err, row) => {
          if (err) return reject(err);
          // 加默认前缀兜底,避免无配置时row为undefined报错
          resolve(row?.prefix ?? "!");
        }
      );
    });

    if (!message.content.startsWith(prefix)) return;

    const args = message.content.slice(prefix.length).trim().split(/ +/g);
    const cmdName = args.shift().toLowerCase();

    if (cmdName.length === 0) return;

    const cmd = client.commands.get(cmdName);
    cmd?.run(client, message, args);
  },
};

方法2:用Node内置工具快速转Promise风格

如果你不想每次写查询都手动包Promise,可以在初始化数据库连接的位置,用Node内置util模块的promisify方法,把回调风格的get方法转换为Promise风格:

// 数据库初始化文件中添加
const { promisify } = require("util");
// 注意要绑定db上下文,避免调用时this指向错误
client.db.get = promisify(client.db.get.bind(client.db));

转换完成后,后续所有调用client.db.get()的位置只要不传回调参数,就会直接返回Promise,可以直接用await接收结果:

// 事件中直接使用即可
const row = await client.db.get(`SELECT prefix FROM "Guilds" WHERE id = ?`, [message.guild.id]);
const prefix = row?.prefix ?? "!";

内容的提问来源于stack exchange,提问作者Zitta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:12:22