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

H2数据库查询Promise未解析,阻塞请求问题求助

H2数据库连接Promise始终pending问题排查与解决

问题描述

正在Web服务器中实现H2数据库连接(数据库运行在服务器模式,支持TCP/IP多连接),但每次调用查询函数时,返回的Promise始终处于pending状态——使用await后完全无响应,无法获取查询结果。

技术栈

  • Node.js 12.11.0(客户指定版本)
  • Express.js(仅需开发3个接口)
  • 客户服务器已部署的H2数据库(用于认证)
  • SQL Server(存储核心业务数据,认证完成后使用)

相关代码

函数调用

userModel.getUsers();

getUsers函数代码

try {
    const connection = await h2.getInstance().getConnection();
    console.log('Connection established');

    return connection.query('SELECT * FROM USERS');
} catch (error) {
    console.error(error);
    throw error;
}

H2连接类(用pg库通过TCP/IP处理连接,也曾尝试jdbc库,结果一致)

class H2Connection {
    // 私有静态字段存储单例实例
    static #instance = null;

    // 私有构造函数,禁止直接实例化
    constructor() {
        this.connection = new pg.Client(h2Conf);
        this.connection.connect();
    }

    static getInstance() {
        // 实例不存在则创建
        if (H2Connection.#instance == null) {
            H2Connection.#instance = new H2Connection();
        }
        // 返回实例
        return H2Connection.#instance;
    }

    // 获取连接的方法
    getConnection() {
       return this.connection;
    }
}

已尝试方案

  • 切换回调与Promise的处理方式
  • 调用函数时使用await,但Promise始终无法解析
  • 调试排查未捕获错误,仅看到服务器请求卡在等待循环
  • 尝试在Promise外部的局部变量中解析返回结果

期望结果

  • 调用服务后能正常输出日志(不用await时能输出日志,但变量值为undefined)
  • 使用then-catch时能输出日志(目前无任何日志输出)
  • 能获取数组或JSON格式的查询结果

问题根源与修复方案

1. 核心问题分析

  • 连接建立未异步等待:H2Connection构造函数中this.connection.connect()是异步操作,但未处理Promise,导致getConnection()返回的连接可能未完成建立,后续query调用卡住。
  • pg库适配兼容性:pg库为PostgreSQL设计,虽H2兼容部分PG协议,但仍可能存在Promise解析异常的兼容性问题。
  • 单例异步初始化缺陷:单例构造函数同步执行,无法处理异步连接逻辑,实例返回时连接未就绪。

2. 针对性修复

方案一:修复连接类的异步初始化逻辑

修改单例模式,确保连接建立完成后再返回实例:

class H2Connection {
    static #instance = null;
    static #connectionPromise = null; // 存储连接初始化Promise,避免重复初始化

    constructor() {
        this.connection = new pg.Client(h2Conf);
    }

    static async getInstance() {
        if (!H2Connection.#instance) {
            if (!H2Connection.#connectionPromise) {
                H2Connection.#connectionPromise = (async () => {
                    const instance = new H2Connection();
                    await instance.connection.connect(); // 等待连接建立完成
                    H2Connection.#instance = instance;
                    return instance;
                })();
            }
            await H2Connection.#connectionPromise;
        }
        return H2Connection.#instance;
    }

    getConnection() {
        return this.connection;
    }
}

同步修改getUsers函数,等待实例初始化完成:

try {
    const h2Instance = await h2.getInstance(); // 等待实例初始化
    const connection = h2Instance.getConnection();
    console.log('Connection established');

    const result = await connection.query('SELECT * FROM USERS'); // 等待查询完成
    return result.rows; // 返回格式化后的结果
} catch (error) {
    console.error(error);
    throw error;
}

方案二:更换H2专用驱动(推荐)

pg库并非H2官方适配驱动,建议改用jdbc库并修复异步逻辑:

const jdbc = require('jdbc');
const jinst = require('jdbc/lib/jinst');

// 初始化JVM(仅需执行一次)
if (!jinst.isJvmCreated()) {
    jinst.addOption('-Xrs');
    jinst.setupClasspath(['path/to/h2-*.jar']); // 替换为实际H2驱动路径
}

class H2Connection {
    static #instance = null;
    static #connectionPromise = null;

    constructor() {
        this.config = {
            url: 'jdbc:h2:tcp://<host>:<port>/<dbname>', // 替换为实际H2地址
            user: '<username>',
            password: '<password>',
            drivername: 'org.h2.Driver',
            minpoolsize: 1,
            maxpoolsize: 10
        };
        this.jdbcConn = new jdbc(this.config);
    }

    static async getInstance() {
        if (!H2Connection.#instance) {
            if (!H2Connection.#connectionPromise) {
                H2Connection.#connectionPromise = (async () => {
                    const instance = new H2Connection();
                    await instance.jdbcConn.initialize(); // 初始化驱动
                    const conn = await instance.jdbcConn.reserve(); // 获取连接
                    instance.connection = conn;
                    H2Connection.#instance = instance;
                    return instance;
                })();
            }
            await H2Connection.#connectionPromise;
        }
        return H2Connection.#instance;
    }

    async query(sql) {
        const statement = await this.connection.createStatement();
        const resultSet = await statement.executeQuery(sql);
        const rows = await resultSet.toObjArray(); // 转换为JSON数组
        await statement.close();
        await this.jdbcConn.release(this.connection); // 释放连接回池
        return rows;
    }
}

方案三:Express路由中正确使用await

确保接口调用时正确处理异步逻辑:

app.get('/users', async (req, res) => {
    try {
        const users = await userModel.getUsers();
        res.json(users);
    } catch (err) {
        res.status(500).json({ error: err.message });
    }
});

3. 验证要点

  • 确认H2服务器正常启动,TCP端口开放,防火墙允许连接
  • 核对数据库配置(地址、端口、用户名、密码、库名)完全正确
  • 查看H2服务器日志,排查连接失败或查询错误记录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:00:38