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

NodeJS回调函数内调用handleDisconnect报错:TypeError问题排查

Node.js MySQL 连接丢失时调用对象方法报错:TypeError: this.handleDisconnect is not a function

我尝试实现MySQL连接断开重连的逻辑,但在回调函数里调用对象方法时遇到了问题。

我的index.js文件代码如下:

const db = require('./models/db.js');
db.connectDb();

db.js文件代码如下:

const mysql = require('mysql');

const database = {

    //连接数据库
    connectDb : function () {
        // 创建连接
        this.db = mysql.createConnection({
            host: 'localhost',
            user: 'root',
            password: '',
            database: 'example'
        });

        this.db.connect(function(err){
            if(err){
              console.log("连接数据库时发生错误。");
              throw err;
            }
            console.log("MySQL Connected...");
        });

        this.db.on('error', function (err) {
            var currentdate = new Date();
            console.log("发生错误 @ ", currentdate," 错误信息:", err);
            if(err.code === 'PROTOCOL_CONNECTION_LOST') {
                this.handleDisconnect();
            } else {
                throw err;
            }
        });
    },

    handleDisconnect: function () {
        this.connectDb();
    }
}
module.exports = database;

服务器启动后MySQL连接成功创建,为测试连接丢失处理逻辑,我重启了MySQL服务,此时this.db.on('error', function (err)被触发,终端输出连接丢失错误信息,但随后出现如下错误:

/home/folder/models/db.js:27
                this.handleDisconnect();
                     ^

TypeError: this.handleDisconnect is not a function
    at Connection.<anonymous> (/home/folder/models/db.js:27:22)
    at Connection.emit (node:events:526:28)
    at Connection._handleProtocolError (/home/folder/node_modules/mysql/lib/Connection.js:423:8)
    at Protocol.emit (node:events:526:28)
    at Protocol._delegateError (/home/folder/node_modules/mysql/lib/protocol/Protocol.js:398:10)
    at Protocol.end (/home/folder/node_modules/mysql/lib/protocol/Protocol.js:116:8)
    at Socket.<anonymous> (/home/folder/node_modules/mysql/lib/Connection.js:94:28)
    at Socket.<anonymous> (/home/folder/node_modules/mysql/lib/Connection.js:526:10)
    at Socket.emit (node:events:538:35)
    at endReadableNT (node:internal/streams/readable:1345:12)
[nodemon] app crashed - waiting for file changes before starting...

我的问题:

该错误是否与在回调函数内调用外部函数有关?能否在对象方法内的回调函数中调用对象的其他方法?或是其他原因导致的问题?


问题原因

这个错误完全是回调函数内的this指向问题。在传统的function()回调里,this的指向会被绑定到触发事件的对象(这里是MySQL的Connection实例),而不是你的database对象,所以自然找不到handleDisconnect方法。

解决方法

有三种常用的方式解决这个问题:

1. 使用箭头函数(推荐)

箭头函数不会绑定自己的this,它会继承外层作用域的this,也就是connectDb方法里的database对象:

this.db.on('error', (err) => {
    var currentdate = new Date();
    console.log("发生错误 @ ", currentdate," 错误信息:", err);
    if(err.code === 'PROTOCOL_CONNECTION_LOST') {
        this.handleDisconnect(); // 这里的this指向database对象
    } else {
        throw err;
    }
});

2. 提前保存this到变量

在回调函数外把this赋值给一个变量(比如self/that),然后在回调里用这个变量访问对象方法:

connectDb : function () {
    const self = this; // 保存当前this指向的database对象
    // ...其他代码

    this.db.on('error', function (err) {
        var currentdate = new Date();
        console.log("发生错误 @ ", currentdate," 错误信息:", err);
        if(err.code === 'PROTOCOL_CONNECTION_LOST') {
            self.handleDisconnect(); // 使用self代替this
        } else {
            throw err;
        }
    });
},

3. 使用bind()绑定this

通过bind()方法手动把回调函数的this绑定到database对象:

this.db.on('error', function (err) {
    var currentdate = new Date();
    console.log("发生错误 @ ", currentdate," 错误信息:", err);
    if(err.code === 'PROTOCOL_CONNECTION_LOST') {
        this.handleDisconnect();
    } else {
        throw err;
    }
}.bind(this)); // 绑定当前this到回调函数

补充说明

当然可以在对象方法的回调里调用对象的其他方法,核心就是要保证回调里的this指向正确的对象。另外,你的重连逻辑还有个小问题:每次调用connectDb都会创建新的连接实例,记得旧连接如果还有残留要销毁,但mysql库在连接断开后会自动清理,所以目前的写法暂时没问题。

内容的提问来源于stack exchange,提问作者dot-wood

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 18:20:33