【问题标题】:Passing data from model to router in node js在节点js中将数据从模型传递到路由器
【发布时间】:2015-10-07 19:16:37
【问题描述】:

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

我的型号代码:

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 或 Users.data 我得到未定义。我真的不明白为什么会这样。我还应该如何通过文件传递数据。

很高兴阅读所有帮助:) 谢谢。

【问题讨论】:

    标签: javascript node.js express module


    【解决方案1】:

    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 变量,但此时您无法再修改导出的变量 - 因为它是它自己的变量,而不仅仅是对 result 的引用。

    你可以做的是:

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

    然后在您的其他文件中:

        var Users = require('../models/users');
    
        Users.getData(function(err, result) {
            // TODO: Error handling.
            console.log(result);
        });
    

    这正是 JavaScript 很容易陷入 回调地狱 的原因,因为它是异步的。

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

    1. 您创建一个变量来保存您的数据和
    2. 创建表的函数

    当您向服务器请求数据(通过 AJAX)时,您会等到获得数据(完成回调),然后才开始创建表:填充变量并调用函数以用数据填充表.

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

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

    (更新:卢卡斯的回答基本上和我说的一样)
    (更新2:错误的处理方式err

    【讨论】:

      【解决方案2】:

      我建议在路由文件中实现查询,有些是这样的:

          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 是因为connection.queryresponse 不适用于connection.query

      【讨论】:

      • 如果我不能将结果保存到查询函数之外的变量中,我该如何创建 API?没有意义:O
      • 这是node.js的一个部分,异步的。这个问题可以解释一下:stackoverflow.com/questions/15635791/…
      【解决方案3】:

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

      ...
      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 中公开 data,并且仅在未定义的情况下使用回调,但这会使您在路由器中的代码更加复杂。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-23
        • 1970-01-01
        • 1970-01-01
        • 2021-12-28
        • 2017-08-24
        • 1970-01-01
        • 1970-01-01
        • 2021-07-29
        相关资源
        最近更新 更多