Node.js OOP中子类Table无法正常调用MySQL连接问题排查
问题诊断与解决方案
问题根源
你的核心问题是数据库连接的异步初始化与子类方法调用的同步执行存在时序冲突:
- Database类的连接操作(比如MySQL的
createConnection或connect)是异步的,但子类Table在实例化后立即调用父类的customQuery或自身的createTable方法,此时父类的connection属性还未完成初始化,自然是undefined。 - 若子类构造函数未正确调用
super()传递上下文,也可能导致this.connection指向错误,但核心矛盾还是异步时序不匹配。
基于事件机制的解决方案
利用Node.js内置的EventEmitter封装连接状态的事件通知,确保子类仅在连接就绪后执行数据库操作。以下是修正后的完整代码:
1. 修正后的Database类(继承EventEmitter)
const mysql = require('mysql'); const EventEmitter = require('events'); class Database extends EventEmitter { constructor(config) { super(); // 必须调用super初始化EventEmitter this.config = config; this.connection = null; this.connect(); } connect() { this.connection = mysql.createConnection(this.config); this.connection.connect((err) => { if (err) { console.error('数据库连接失败:', err); this.emit('error', err); return; } console.log('数据库连接成功'); this.emit('connected'); // 连接就绪后触发事件 }); } customQuery(sql, params) { return new Promise((resolve, reject) => { if (!this.connection) { return reject(new Error('数据库连接未就绪')); } this.connection.query(sql, params, (err, results) => { if (err) reject(err); else resolve(results); }); }); } } module.exports = Database;
2. 修正后的Table子类
const Database = require('./Database'); class Table extends Database { constructor(config, tableName) { super(config); this.tableName = tableName; // 监听父类的连接就绪事件 this.on('connected', () => { this.createTable(); // 连接就绪后再执行建表操作 }); this.on('error', (err) => { console.error(`表${this.tableName}操作失败:`, err); }); } async createTable() { try { const sql = `CREATE TABLE IF NOT EXISTS ${this.tableName} ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP )`; const result = await this.customQuery(sql); console.log(`表${this.tableName}创建成功或已存在`, result); } catch (err) { console.error('建表失败:', err); } } } module.exports = Table;
3. index.js入口文件
const Table = require('./Table'); const dbConfig = { host: 'localhost', user: 'root', password: 'your_password', database: 'your_db' }; // 实例化Table,自动等待连接就绪后执行建表 const userTable = new Table(dbConfig, 'users'); // 如需手动调用其他查询,也要确保连接就绪 userTable.on('connected', async () => { const result = await userTable.customQuery('SELECT 1 + 1 AS solution'); console.log('查询结果:', result); });
关键改进点
- Database类继承
EventEmitter,连接成功时触发connected事件,失败时触发error事件,让子类可以监听状态。 - Table子类在构造函数中监听
connected事件,确保只有连接就绪后才执行createTable或customQuery。 - 将
customQuery封装为Promise,结合async/await让异步操作更易读,同时增加了连接状态检查,避免未就绪时调用。
内容的提问来源于stack exchange,提问作者mastercordy
相关产品推荐
相关产品推荐

