简体   繁体   English

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

[英]Passing data from model to router in node js

I am trying to pass some data from my db to the router which then passes the data to the view. 我试图将一些数据从我的数据库传递到路由器,然后路由器将数据传递给视图。

My model code : 我的型号代码:

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)
}

Now to my route file : 现在到我的路线档案:

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;

When I console.log Users or Users.data I get undefined. 当我在console.log用户或Users.data时,我得到了未定义。 I don't really get why this is the case. 我真的不明白为什么会这样。 How else am I supposed to pass data along the files. 我怎么能沿着文件传递数据。

All help is gladly read :) Thank you. 很乐意阅读所有帮助:)谢谢。

module.exports are being evaluated the second you require and variables are not passed by reference in this case. 在这种情况下, module.exports正在评估您require的第二个,并且变量不会通过引用传递。

What that means for your code is the following: 这对您的代码意味着什么:

    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.
    }

When you now require the above file in another file of your code, the above is being evaluated and saved straight away (result is undefined at that point in time, hence it is also undefined when it exports). 当您现在require在代码的另一个文件中使用上述文件时,上面的内容正在进行评估并立即保存 (结果在该时间点未定义,因此在导出时也未定义)。 Your query is being executed and written into the result variable, but at that point in time you can not modify the exported variable anymore – because it is it's own variable and not merely a reference to result ). 您的查询正在执行并写入result变量,但在那个时间点您不能再修改导出的变量 - 因为它是它自己的变量而不仅仅是对result的引用。

What you could do is the following: 你能做的是以下几点:

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

    module.exports = {
        getData: getData
    }

and then in your other file: 然后在你的另一个文件中:

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

    Users.getData(function(err, result) {
        // TODO: Error handling.
        console.log(result);
    });

That's exactly why it's so easy with JavaScript to end up in callback hell , because of it's asynchronous nature. 这就是为什么用JavaScript最终在回调地狱中这么容易,因为它具有异步性质。

The above is the exact same situation as if you, fe, want to get some data via AJAX from a server and then fill tables with it. 以上是完全相同的情况,就好像你想要从服务器通过AJAX获取一些数据,然后用它填充表格一样。 When you start creating the table before you have the data (so the AJAX request is not yet complete), you end up with an empty table. 当您获得数据之前开始创建表(因此AJAX请求尚未完成)时,您最终得到一个空表。 What could do is: 可以做的是:

  1. you create a variable that holds your data and 你创建一个保存数据的变量
  2. a function that creates the table 一个创建表的函数

when you then ask the server for the data (via AJAX) you wait until you get the data (completion callback) and only then you start creating the table: filling your variable and calling the function to fill the table with the data. 当你然后向服务器询问数据(通过AJAX)时,你要等到获得数据(完成回调),然后才开始创建表:填充变量并调用函数来填充表中的数据。

Server-Side JavaScript is the same as client-side. 服务器端JavaScript与客户端相同。 Never forget this. 别忘了这个。

As a little homework for the reader: the way to get out of callback hell is by reading up on promises – a pattern/architecture which reduces indents and saves lots of headaches :) 作为读者的一个小作业:摆脱回调地狱的方法是阅读承诺 - 一种减少缩进并节省大量头痛的模式/架构:)

(update: Lucas' answer is basically telling the same thing as I did) (更新:卢卡斯的回答基本上和我说的一样)
(update 2: wrong way of handling err ) (更新2:处理err错误方法)

I suggest realize the consult in the route file, some like this: 我建议在路由文件中实现咨询,有些像这样:

    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;

But you can configure the connection with database in another file, in libs/mysql_connect.js . 但是您可以在libs/mysql_connect.js中的另一个文件中配置与数据库的连接。

The undefined is caused because the response of connection.query don't works out of the connection.query . 导致undefined是因为connection.queryresponse不能在connection.query

If you really want the query to run only once and then just re-use the already queried data, I think you are after something like this for your model: 如果你真的希望查询只运行一次,然后只是重新使用已经查询的数据,我认为你正在为你的模型做这样的事情:

...
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

In your router, you'd then use it like this: 在您的路由器中,您可以像这样使用它:

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

The first time you call getData , you'll get a fresh result, and on subsequent calls you get the cached result. 第一次调用getData时 ,您将获得一个新结果,并在后续调用中获得缓存结果。

While you could expose data in mymodel directly, and only use the callback in case it is still undefined, that'd make your code in the router more convulated. 虽然您可以直接在mymodel中公开数据 ,并且仅在未定义的情况下使用回调,但这会使您在路由器中的代码更加精确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM