将数据从模型传递到节点js中的路由器

时间:2015-10-07 19:16:37

标签: javascript node.js express module

我正在尝试将一些数据从我的数据库传递到路由器,然后路由器将数据传递给视图。

我的型号代码:

var mysql = require('mysql');

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

var result; // empty var which should later be filled with the querys result

connection.connect();

var query = connection.query('SELECT * FROM users', function(err, res, fields) {
  if (err) throw err;

  result = res; // overwrite result with the querys result
  console.log(res); // This prints out everything I need
});


module.exports = {
  data: result // should contain the query result (= 2 objects in this case)
}

现在我的路线档案:

var express = require('express');
var router = express.Router();

var Users = require('../models/users');

console.log(Users.data);
/* GET home page. */
router.get('/users', function(req, res) {
    res.render('api', { data: Users.data, title: "Test API Output" });
});

module.exports = router;

当我在console.log用户或Users.data时,我得到了未定义。我真的不明白为什么会这样。我怎么能在文件中传递数据。

很乐意阅读所有帮助:)谢谢。

3 个答案:

答案 0 :(得分:5)

在这种情况下,

module.exports正在评估第二个require,而变量通过引用传递。

对您的代码意味着什么:

    var result;  // result is "undefined" because it does not contain a value here
    // You are doing your DB queries here...
    module.exports = {
        data: result  // ...and because the query has not finished here yet, result 
                      // is still undefined. 
        // This is also a good example of a so called "race condition", because there is a 
        // slight (improbable) chance that the query might have already finished. 
        // Hence, it could happen that sometimes result is already filled.
    }

当您现在require上述文件放在代码的另一个文件中时,上面的内容正在评估中并且已保存(结果在该时间点未定义,因此它是它出口时也未定义)。 您的查询正在执行并写入result变量,但在那个时间点您不能再修改导出的变量 - 因为它是它自己的变量而不仅仅是对{{1的引用}})。

您可以做的是:

result

然后在你的另一个文件中:

    function getData(callback) {
        connection.query('SELECT * FROM users', function(err, res, fields) {
            callback(err, res);
        });
    }

    module.exports = {
        getData: getData
    }

这正是为什么JavaScript能够以回调地狱结束这么容易的原因,因为它具有异步性质。

以上是完全相同的情况,就好像你想要从服务器通过AJAX获取一些数据,然后用它填充表格一样。当您在之前开始创建表时,您拥有数据(因此AJAX请求尚未完成),您最终得到一个空表。可以做的是:

  1. 您创建一个保存数据的变量
  2. 创建表格的函数
  3. 当你向服务器询问数据(通过AJAX)时,你会等到获得数据(完成回调),然后才开始创建表:填充变量并调用函数来填充表中的数据

    服务器端JavaScript与客户端相同。永远不要忘记这一点。

    作为读者的一个小作业:摆脱回调地狱的方法是阅读 promises - 一种减少缩进和节省批量的模式/架构头疼:)

    (更新:Lucas'答案基本上和我说的一样) (更新2:错误的处理方式 var Users = require('../models/users'); Users.getData(function(err, result) { // TODO: Error handling. console.log(result); });

答案 1 :(得分:1)

我建议在路由文件中实现咨询,有些像这样:

    var express = require('express');
    var router = express.Router();

    var Users = require('../models/users');

    var mysql = require('mysql');

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

   var result; // empty var which should later be filled with the querys result

connection.connect();

    /* GET home page. */
    router.get('/users', function(req, res) {        

        var query = connection.query('SELECT * FROM users', function(err, res, fields) {
            if (err) throw err;

            result = res; // overwrite result with the querys result
            res.render('api', { data: res.data, title: "Test API Output" });
        });
    });

    module.exports = router;

但您可以在libs/mysql_connect.js中的另一个文件中配置与数据库的连接。

导致undefined的原因是response connection.query的{​​{1}}无法使用connection.query

答案 2 :(得分:1)

如果你真的希望查询只运行一次,然后重新使用已经查询过的数据,我认为你的模型就是这样:

...
var data;
var mymodel = {};
...
mymodel.getData = function(callback) {
    if(data) {
        callback(data);
    } else {
        db.query('select * from users', function(err,res,fields) {
            // error checking and such
            data = res;
            callback(data);
        });
    }
}
module.exports = mymodel

在您的路由器中,您可以像这样使用它:

...
router.get('/users', function(req, res) {
    Users.getData(function(mydata) {
        res.render('api', { data: mydata, title: "Test API Output" });
    });
});

第一次调用 getData 时,您将获得一个新结果,并在后续调用中获得缓存结果。

虽然您可以直接在 mymodel 中公开数据,并且仅在仍未定义的情况下使用回调,但这会使您在路由器中的代码更多convul​​ated。