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

Node.js+Express+MySQL连接池Promise化及错误处理咨询

Node.js + Express + MySQL连接池:Promise封装与错误处理优化方案

嘿,针对你用Node.js+Express+MySQL连接池的这套实现,我先帮你梳理下现有代码的问题,再给出几个实用的错误处理优化方案:

一、先修复基础Promise封装的核心漏洞

你当前的getConnection代码有个致命问题:获取到连接后没有调用resolve(connection),这会导致Promise永远处于pending状态,调用方永远拿不到连接。另外,错误信息最好保留原始错误对象,不要只转成字符串,这样后续能拿到错误码、堆栈等关键排查信息。

修复后的代码:

exports.getConnection = () => {
  return new Promise((resolve, reject) => {
    pool.getConnection((err, connection) => {
      if (err) {
        // 用Error对象包装,保留原始错误作为cause,方便后续排查
        reject(new Error(`无法从连接池获取连接: ${err.message}`, { cause: err }));
        return;
      }
      // 必须resolve拿到的连接,否则Promise会一直挂起
      resolve(connection);
    });
  });
};

二、连接池层面的全局错误监听

连接池本身可能出现底层错误(比如数据库连接断开、创建连接超时),如果不监听这些错误,可能会导致未捕获异常终止进程。给连接池添加全局错误监听:

// 监听连接池全局错误
pool.on('error', (err) => {
  console.error('MySQL连接池全局错误:', err);
  
  // 针对常见错误类型做针对性处理
  switch(err.code) {
    case 'PROTOCOL_CONNECTION_LOST':
      console.log('数据库连接已断开,尝试重新初始化连接池...');
      // 这里可以根据你的逻辑重新创建连接池(如果需要)
      break;
    case 'ER_ACCESS_DENIED_ERROR':
      console.error('数据库权限验证失败,请检查账号密码');
      break;
    default:
      console.error('未知连接池错误:', err);
  }
});

三、Express全局错误处理中间件

确保所有路由中的数据库操作错误都能被统一捕获,避免进程崩溃,同时给客户端返回合理的错误响应:

注意:这个中间件必须放在所有路由定义之后!

app.use((err, req, res, next) => {
  // 打印完整错误日志(生产环境可以只打印关键信息)
  console.error('应用全局错误:', err);
  
  const isProduction = process.env.NODE_ENV === 'production';
  // 根据环境返回不同的错误信息
  res.status(err.statusCode || 500).json({
    message: isProduction ? '服务器内部错误' : err.message,
    // 开发环境返回堆栈信息方便调试
    ...(!isProduction && { stack: err.stack }),
    // 传递原始错误的原因(如果有的话)
    ...(err.cause && { cause: err.cause.message })
  });
});

四、数据库操作中的连接释放与错误捕获

不管数据库操作成功还是失败,必须释放连接,否则会导致连接池耗尽,无法处理新请求。推荐用async/await结合try/catch/finally来实现:

async function getUsersList() {
  let connection;
  try {
    // 获取连接
    connection = await getConnection();
    // 执行查询
    const [rows] = await connection.query('SELECT * FROM users WHERE is_active = ?', [1]);
    return rows;
  } catch (err) {
    console.error('查询用户列表失败:', err);
    // 可以在这里针对不同错误类型做重试、告警等操作
    // 比如死锁错误(ER_LOCK_DEADLOCK)可以重试1-2次
    if (err.code === 'ER_LOCK_DEADLOCK' && retryCount < 2) {
      retryCount++;
      return getUsersList();
    }
    // 抛出错误让全局中间件处理
    throw err;
  } finally {
    // 无论成功失败,都释放连接回池
    if (connection) {
      connection.release();
    }
  }
}

五、进阶错误处理策略

  • 错误分类处理:根据MySQL错误码(比如ER_BAD_FIELD_ERROR表示字段不存在,ER_DUP_ENTRY表示唯一键冲突)返回对应HTTP状态码(400、409等),让客户端更清楚错误原因
  • 重试机制:针对临时错误(连接超时、死锁)实现有限次数的重试,提升系统容错性
  • 日志上报:把错误信息(包括请求上下文、错误堆栈)上报到日志系统(比如Winston、Bunyan),方便后续排查问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:26:56