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

调用实例属性遇TypeError报错,及DatabaseController效率疑问求解

问题分析与解决方案

一、报错原因:this 上下文丢失

你遇到的 TypeError: Cannot read property 'sendError' of undefined 核心问题是回调函数里的 this 指向发生了偏移,不再指向 SocketHelper 的实例。

看这段 SocketHelper.js 里的代码:

SocketHelper.prototype.getUserById = function(id, callback){
  DatabaseController.databaseQuery("SELECT * FROM users WHERE id = ?", id, function (error, user) {
    if(error || !user.length > 0) {
      return this.instance.sendError("Couldn't find a user with ID: " + id);
    }
    return callback(null, user[0]);
  });
};

当 databaseQuery 执行完毕调用这个匿名回调时,函数内部的 this 已经脱离了 SocketHelper 实例的上下文(普通函数作为回调时,this 默认指向全局对象或严格模式下的 undefined),所以 this.instance 自然就是 undefined,访问 sendError 就触发了报错。

修复方案(三种任选其一)

  1. 提前保存实例引用:
    在 getUserById 开头把当前实例存到变量里,回调里用这个变量代替 this:
    SocketHelper.prototype.getUserById = function(id, callback){
      const self = this; // 保存当前SocketHelper实例
      DatabaseController.databaseQuery("SELECT * FROM users WHERE id = ?", id, function (error, user) {
        if(error || !user.length > 0) {
          return self.instance.sendError("Couldn't find a user with ID: " + id);
        }
        return callback(null, user[0]);
      });
    };
    
  2. 使用箭头函数继承上下文:
    箭头函数不会绑定独立的 this,会直接继承外层作用域的 this:
    SocketHelper.prototype.getUserById = function(id, callback){
      DatabaseController.databaseQuery("SELECT * FROM users WHERE id = ?", id, (error, user) => {
        if(error || !user.length > 0) {
          return this.instance.sendError("Couldn't find a user with ID: " + id);
        }
        return callback(null, user[0]);
      });
    };
    
  3. 用 bind 强制绑定上下文:
    给回调函数手动绑定当前实例的 this:
    SocketHelper.prototype.getUserById = function(id, callback){
      DatabaseController.databaseQuery("SELECT * FROM users WHERE id = ?", id, function (error, user) {
        if(error || !user.length > 0) {
          return this.instance.sendError("Couldn't find a user with ID: " + id);
        }
        return callback(null, user[0]);
      }.bind(this)); // 绑定当前SocketHelper实例
    };
    

二、DatabaseController 的效率分析与优化建议

当前你的 DatabaseController 是可用的,但存在可优化的空间:
每次执行 databaseQuery 都手动调用 pool.getConnection() 获取连接、执行后再 connection.release() 释放,虽然用了连接池,但这种手动管理方式冗余且没必要——mysql 连接池本身提供了 pool.query() 方法,它会自动处理连接的获取与释放,既减少重复代码,也避免了忘记释放连接导致的连接泄漏风险。

优化后的示例代码:

// 假设你已经完成了pool的初始化
module.exports = {
  // 如果没有单独使用createDatabaseConnection的场景,这个方法可以直接移除
  createDatabaseConnection: function(callback) {
    pool.getConnection(function(error, connection) {
      if(error){ return callback(error); }
      return callback(null, connection);
    });
  },
  databaseQuery: function(query, parameters, callback) {
    if(parameters){
      query = mysql.format(query, parameters);
    }
    // 直接使用pool.query,自动管理连接生命周期
    pool.query(query, function(error, result) {
      if(error){ return callback(error); }
      return callback(null, result);
    });
  }
};

优化后不仅代码更简洁,连接池的复用逻辑也会更高效,因为 pool.query 内部会优化连接的分配与回收策略。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:04:55