浏览Node.js、Express和mysql模块

4
我正在尝试整合node.js的express框架和mysql模块https://npmjs.org/package/mysql。我已经通过使用express命令行建立了一个简单的应用程序,并且我还声明了一个模块来处理一些数据库属性。
我的DB模块设置如下:
app.js
node_modules
|___db
     |
     node_modules
           |___mysql

mysql模块已设置为db模块的依赖项。

在db模块的index.js中,我设置了一些模块导出以供应用程序访问:

/*
 * Connection params for database
 */

var mysql = require('mysql');
var connection = mysql.createConnection({
  host: 'localhost',
  user: 'user',
  password: 'password',
  database: 'database',
});

var connect = connection.connect(function(err){
  if(!err){
        console.log("You are connected to the database.");
  }
  else{
        throw err;
  }
});

var end = connection.end(function(err){
  if(!err){
        console.log("Mysql connection is terminated.")
  }
  else{
        throw err;
  }
});

module.exports = {
  connect: connect,
  connection: connection,
  end: end,
}

在我的app.js文件中,我正在引用我的db模块并指定一些路由。我还尝试在客户端路由的app.get方法中使用路由中间件函数(estDb):
/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , clients = require('./routes/clients')
  , user = require('./routes/user')
  , http = require('http')
  , path = require('path')
  , db = require('db');

var app = express();

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

var estDb = function(req, res, next){
  db.connect;
  db.connection.query("SELECT * FROM Table", function(err, results){
        if(!err){
          req.results = results;
        }
        else{
          throw err;
        }
  });
  db.end;
  next();
}

app.get('/', routes.index);
app.get('/clients', estDb, clients.view);

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

问题:我遇到的问题是似乎我的数据库函数(我的模块导出)在启动应用程序时被调用,因为我看到了日志:

Express server listening on port 3000
You are connected to mysql.
Mysql connection is terminated.

并不是当请求url http://localhost/clients时(这是我定义的路由),才会执行下面的操作。正如您所看到的,它在控制台记录了“Express server listening on port 3000”消息后立即触发db.connect()和db.end()方法--这使我相信它来自我使用的自定义db模块。随后,当我访问路由http://localhost/clients时,会出现错误:

500 Error: Cannot enqueue Query after invoking quit.

如果我从db模块中删除connection.end()函数,我就能够连接到数据库并检索结果;然而,如果我重新加载页面并再次尝试加载结果,就会出现错误:

Cannot enqueue Handshake after already enqueuing a Handshake

我不明白为什么我启动应用程序时我的模块导出会触发?我认为这就是我遇到麻烦的地方。
有什么建议或帮助将是非常棒的。
2个回答

3
我不明白为什么我导出的模块在启动应用程序时就被激活了? 我认为这就是我遇到问题的地方。
我认为这是由于以下代码引起的:
var mysql = require('mysql');
var connection = mysql.createConnection({
  host: 'localhost',
  user: 'user',
  password: 'password',
  database: 'database',
});

在这里,你实际上是在连接数据库,而不是定义一个函数,当调用时会连接到数据库。


我也会关注Chris提出的有关estDb中缺少括号的建议。 - Hector Correa
嗨,Hector,感谢你的关注。你通过强制我查看db模块中声明的内容,指引了我正确的方向。我遇到的问题实际上不是你之前指出的createConnection()方法,而是随后的connect()end()方法。我以为通过设置connect = connection.connect()就可以将函数存储在变量中,但你指出需要使用connect = function(connection){ connection.connect(); }。感谢你的建议。 - tthenne

2

您收到的日志消息不是来自该代码(没有“您已连接到mysql”)吗? 请尝试以下操作:

db.connect;

应该是

db.connect();

因为您想要执行该函数。在执行next()之前,您还需要等待查询完成。

var estDb = function(req, res, next){
  db.connect();
  db.connection.query("SELECT * FROM Table", function(err, results){
        if(!err){
          req.results = results;
          next();
        }
        else{
          throw err;
        }
  });
  db.end();
}

编辑:这里发生的情况是当您需要它时,db模块中的代码会立即执行。您想做的是:

var connect = function(){
  connection.connect(function(err){
    if(!err){
      console.log("You are connected to the database.");
    }
    else{
      throw err;
    }
  })
};

接着,你可以按照我的帖子中所示调用db.connect()end()同理)。如果把db.connect放在一行中(不加括号),什么也不会发生。


嗨,Chris,感谢你的回答。在查询的回调函数中执行next();函数是正确的,而不是在查询之外执行。但是这些函数正在引用模块中的导出变量(巧合的是我已将其设置为函数),因此它们应该保持为db.connectdb.end--只是为了确保,我使用db.connect()运行了应用程序,结果显示该方法未定义。如果您直接从mysql模块调用,则使用connection.connect()是正确的,但在这种情况下,我将connect()方法作为变量导出。 - tthenne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接