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

JavaScript使用Promise/async-await操作MySQL时无法等待查询完成

问题分析与解决方案

核心问题

你的代码存在几个关键问题导致异步流程失控:

  • 重复执行USE查询(连接配置里已指定database,无需手动执行)
  • 调用异步函数sequentialQueries时未使用await,主程序不等待异步操作完成就继续执行
  • 手动拼接SQL存在注入风险,且异步流程未统一管理
  • 数据库连接未在所有操作完成后正确关闭

修正后的代码

const mysql = require('mysql');

const selectedDB = 'ItalianVerbs';
const str_VerbCols = "(infinitive, english, auxiliary, gerund, participle)";

// 创建连接,配置里已指定database,无需手动执行USE
const g_con = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'Kl1n&on0per@',
  database: selectedDB
});

// 封装mysql查询为通用Promise方法
function queryPromise(sql, params) {
  return new Promise((resolve, reject) => {
    g_con.query(sql, params, (err, res) => {
      if (err) reject(err);
      else resolve(res);
    });
  });
}

// 构建参数化INSERT查询(避免SQL注入)
function buildInsertQuery(valList) {
  if (valList.length < 5) {
    console.error("[buildInsertQuery] 错误:插入行的参数数量不足");
    return null;
  }
  // 使用?作为占位符,由mysql包自动处理参数转义
  return {
    sql: `INSERT INTO Verb ${str_VerbCols} VALUES (?, ?, ?, ?, ?)`,
    params: valList
  };
}

// 统一执行所有插入操作的函数
async function insertAllVerbs(verbList) {
  try {
    // 等待连接建立成功
    await new Promise((resolve, reject) => {
      g_con.connect(err => {
        if (err) reject(err);
        else resolve();
      });
    });

    console.log("数据库连接成功");

    // 按顺序执行插入操作(如需并行可改用Promise.all)
    for (const verb of verbList) {
      const queryData = buildInsertQuery(verb);
      if (!queryData) continue;
      
      console.log(`*** 执行查询: ${queryData.sql}`, queryData.params);
      await queryPromise(queryData.sql, queryData.params);
      console.log(`已插入动词: ${verb[0]}`);
    }

    console.log("所有插入操作完成");
    return 0;
  } catch (err) {
    console.error("操作出错:", err);
    return err;
  } finally {
    // 无论成功失败,最后关闭数据库连接
    g_con.end();
    console.log("数据库连接已关闭");
  }
}

// 测试数据
const verbList = [
  ["adorare", "adore", "avere", "adorando", "adorato"],
  ["abitare", "dwell", "avere", "abitando", "abitato"],
  ["abbassare", "let-down", "avere", "abbandonando", "abbandonato"]
];

// 启动执行,等待所有操作完成后再退出程序
insertAllVerbs(verbList)
  .then(result => {
    console.log("执行完成,退出程序");
    process.exit(result === 0 ? 0 : 1);
  })
  .catch(err => {
    console.error("执行失败:", err);
    process.exit(1);
  });

关键改进点

  • 通用Promise封装:把mysql.query封装成通用方法,避免重复编写异步逻辑
  • 参数化查询:用?占位符替代手动拼接字符串,彻底规避SQL注入风险
  • 异步流程管控:用for...of循环替代forEach(forEach无法等待异步操作),确保插入按顺序执行;若需并行执行可改用Promise.all
  • 连接生命周期管理:等待连接建立成功后再执行操作,所有任务完成后统一关闭连接
  • 主程序等待机制:通过then/catch等待所有异步操作完成后再退出,确保查询全部执行完毕

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 17:44:50