【问题标题】:module.exports scope and node-mysqlmodule.exports 范围和 node-mysql
【发布时间】:2013-10-26 12:21:32
【问题描述】:

我有 database.js 文件连接到 db 并管理连接我导出连接并在我的应用程序中重用它

    var mysql = require('mysql');

    pool = mysql.createPool({
        host: cfg.mysql.host,
        user: cfg.mysql.user,
        password: cfg.mysql.pass,
        database: cfg.mysql.db,
        port: cfg.mysql.port
    });


    function handleDisconnect() {
    pool.getConnection(function(err, cnt) {
    module.exports.connection = cnt;
    });

    pool.on('error', function (err) {
      console.log(err);
    });
    };

    handleDisconnect();
    process.on('uncaughtException', function (err) {
      console.error(err.code);
    if(err.code === "PROTOCOL_CONNECTION_LOST")
    handleDisconnect();
      console.log("Node NOT Exiting...");
    });

app.js

    var db = require('./database');
     app.get('/test', function(req, res) {
        db.connection.query('SELECT * from table', function(err, result) {
           console.log(result);
          });
        }

这很好用。我的问题是mysql服务器断开连接时。我通过调用 handleDisconnect() 函数来获取新连接来处理此错误。但是,当发生这种情况时,当我导航到浏览器 /test 时,我的 app.js 中的连接是未定义的

TypeError: Cannot call method 'query' of undefined

想法?

【问题讨论】:

    标签: javascript mysql node.js


    【解决方案1】:

    您可以在数据库服务器上的每个查询之后简单地将连接放回池中 这是一个例子

    db.js

    var mysql = require('mysql');
    var pool  = mysql.createPool({
      host     : 'localhost',
      user     : 'root',
      password : 'root',
      database : 'test',
      port: 8889
    });
    
    exports.getConnection = function(callback) {
        pool.getConnection(function(err, connection) {
            callback(err, connection);
        });
    };
    

    app.js

    var db = require('./db');
    var http = require("http");
    var server = http.createServer(function(request, response) {
        db.getConnection(function(err, connection){
            if(!err){
                connection.query('SELECT * from users' , function(err, rows) {
                    var users = '';
                    for (var i = 0; i < rows.length; i++) {
                        users += rows[i].name + "<br />";
                    }
                    connection.release(); // always put connection back in pool after last query
                    response.writeHead(200, {"Content-Type": "text/html"});
                    response.write("<!DOCTYPE html>");
                    response.write("<html>");
                    response.write("<head>");
                    response.write("<title>Hello World Page</title>");
                    response.write("</head>");
                    response.write("<body>");
                    response.write(users);
                    response.write("</body>");
                    response.write("</html>");
                    response.end();
               });
            }else{
                response.writeHead(200, {"Content-Type": "text/html"});
                response.write("<!DOCTYPE html>");
                response.write("<html>");
                response.write("<head>");
                response.write("<title>Hello World Page</title>");
                response.write("</head>");
                response.write("<body>");
                response.write(err.toString());
                response.write("</body>");
                response.write("</html>");
                response.end();
            }
        });
    });
    server.listen(9999);
    console.log("Server is listening localhost:9999");
    

    【讨论】:

      【解决方案2】:

      更新:请参阅下面的第一条评论,以更正我对问题的[错误]理解。我将保留此回复,而不是删除它,因为它涉及多个问题。

      您不能继续重新分配给 module.exports。它不起作用,因为导出只在 require() 时间发生一次(实际上,我怀疑上面的代码完全起作用只是因为 pool.getConnection 同步执行,即在回调中分配给 module.exports 通常不安全) .这是发生了什么:

      在 app.js 中你可以:var db = require('./database');

      它存储的不是对 module.exports(数据库.js)的引用,而是对分配给 module.exports 的对象(即连接对象)的引用。当该对象由于断开连接而被销毁时,app.js 中的变量“db”什么都没有(请注意,node-mysql 文档很清楚您不能重用连接对象)。您真正想要做的是向 app.js 返回一个新的连接对象,但这是不可能的,因为 app.js 调用只需要一次。

      我了解到您想对 app.js 隐藏重新建立的连接。一种方法是将 node-mysql 连接对象包装在您自己的 database.js 对象中,并将后者返回给 app.js。这个被包装的对象可以在调用它的query()方法时从池中获取一个连接,然后调用获取到的连接的query()方法。以此类推。

      【讨论】:

      • 连接没有分配给module.exports,它分配给module.exports.connection,所以应该可以正常工作(尽管我同意当前的设置有点可疑)。
      • 不错,我没注意到。
      【解决方案3】:

      首先检查handleDisconnect 中的pool.getConnection 是否会引发错误。由于您没有在重新连接之前建立超时以防连接丢失,因此立即调用pool.getConnection 可能会因为同样的问题而失败。

      此外,在连接丢失和 handleDisconnect 重新连接之间,任何传入的 HTTP 请求都无法执行数据库查询,因此应在尝试运行查询之前检查 db.connection 是否确实有效。

      那,或者您也需要处理 Express 路由中的错误,例如使用错误处理程序路由(应放置在您的路由/中间件设置的最后某个位置):

      // middleware setup
      ...
      // routes setup
      ...
      // finally:
      app.use(function(err, req, res, next) {
        res.send(500, err.message); // or whatever you want to send back in case of errors.
      });
      

      【讨论】:

        猜你喜欢
        • 2022-07-12
        • 2015-09-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-11
        • 1970-01-01
        • 2016-06-02
        • 2012-02-24
        相关资源
        最近更新 更多