在Express中的多个SELECT查询之后呈现视图

我在Node.JS和Express框架中有点新,我对下面的代码有很大的问题:

app.get('/student', function(req, res) { var dbRequest = 'SELECT * FROM Students WHERE IDCard = \'' + req.query['id'] + '\''; db.all(dbRequest, function(error, rows) { if(rows.length !== 0) { /* Save data. */ } else res.render('incorrect_student'); /* Render the error page. */ }); dbRequest = 'SELECT * FROM Groups WHERE Name = \'' + req.query['group'] + '\''; db.all(dbRequest, function(error, rows) { /* Add selected data to previous saved data. */ } }); res.render('student', {data: /* data from both queries above */}); }); 

正如我在评论块中写的,我想:执行第一个select查询,保存来自对象的数据,执行第二个查询,再次将接收到的数据保存在其他对象中,然后最终呈现从这两个查询传递数据的页面。 我的问题是,最好的办法是什么?

我知道有一个匿名函数引起的问题。 我试图解决这个问题超过五个小时,如下所示:

  1. 在匿名函数中克隆对象到另一个对象,然后将其传递给res.render 。 这个解决scheme不起作用,因为拷贝对象的值在这个函数之外是不可见的(未定义的) – 只在其内部。
  2. 渲染学生页面两次 – 当然这真的很天真。
  3. db.all命令更改为db.prepare ,然后将db.run更改为无效
  4. 通过匿名函数返回对象,然后将其分配给app.getvar dbRequest之间定义的外部对象。 结果如第一点所述。

我也有一个想法来创build“子页面”包含学生页面的部分,它只需要一个查询的variables。 另一个想法是使用dbreqresapp对象的一些其他函数。 但是,正如我之前所说,我是Express的新手,我不知道如何实现我的上述想法。

请注意,这是不可能的表 – 实际上,我想做4-5查询,然后呈现我的看法。 我正在使用SQLite3数据库。

非常感谢您的帮助! 我希望你能帮我解决我的问题。

在你的情况下,我会把数据库调用拆分成不同的调用,并利用next中间件function。

它看起来像这样:

 function findStudent(req, res, next) { var dbRequest = 'SELECT * FROM Students WHERE IDCard = \'' + req.query['id'] + '\''; db.all(dbRequest, function(error, rows) { if(rows.length !== 0) { req.students = rows; return next(); } res.render('incorrect_student'); /* Render the error page. */ }); } function findGroups(req, res, next) { dbRequest = 'SELECT * FROM Groups WHERE Name = \'' + req.query['group'] + '\''; db.all(dbRequest, function(error, rows) { /* Add selected data to previous saved data. */ req.groups = rows; next(); } }); } function renderStudentsPage(req, res) { res.render('student', { students: req.students, groups: req.groups }); } app.get('/student', findStudent, findGroups, renderStudentsPage); 

当你GET /student ,你首先打电话给findStudent 。 数据库调用完成后,它将显示错误页面或调用next()。 接下来调用下一个函数findGroups ,然后调用renderStudentsPage 。 您可以将数据存储在req对象上,当您向下移动函数行时。

希望这有助于,这里是更多的信息: http : //expressjs.com/guide/using-middleware.html


编辑/注:

我之前没有提到它,但是如果在调用next()时传入参数,将触发error handling状态。 除非遇到错误实例,否则约定next()是无参数的。

你想从数据库调用中分离出UI渲染方面,所以进一步,你的代码看起来像这样:

 function findStudent(req, res, next) { var dbRequest = 'SELECT * FROM Students WHERE IDCard = \'' + req.query['id'] + '\''; db.all(dbRequest, function(error, rows) { if (error || !rows.length) { return next(error); } req.students = rows; return next(); }); } 

然后在你的代码中的其他地方,你可以处理渲染错误页面。

我知道这是一个古老的问题,但对于任何仍然有问题和使用MongoDB的人来说,这是对我有用的。

 //index.js const express = require('express'); const router = express.Router(); function getData (req, res, next) { var db = req.db; var collection = db.get('usercollection'); collection.find({}, {}, function(e, docs) { req.data = docs; return next(); }); } function getVendor (req, res, next) { var db = req.db; var collection = db.get('usercollection'); collection.distinct("vendor", function(e, docs) { req.vendor = docs next(); }); } function getType (req, res, next) { var db = req.db; var collection = db.get('usercollection'); collection.distinct("type", function(e, docs) { req.type = docs next(); }); } function renderData(req, res) { res.render('index', { data: req.data, vendor: req.vendor, type: req.type }); } /* GET home page. */ router.get('/', getData, getVendor, getType, renderData); module.exports = router; 

然后在你的ejs文件里面

 //index.ejs <body> <div id="app"> <h1>Choose a Vendor</h1> <template v-for="vendor in values.vendor"> <label :for="vendor">{{ vendor }}</label> <input type="radio" :value="vendor" v-model="flagpole.vendor"> </template> <div> <template v-for="type in values.type"> <label :for="type">{{ type }}</label> <input type="radio" :value="type" v-model="flagpole.type"> </template> </div> </div> <script type="text/javascript"> var vendor = <%- JSON.stringify(vendor) %> var type = <%- JSON.stringify(type) %> var vm = new Vue({ el: '#app', data: { values: { vendor: vendor, type: type }, flagpole: { vendor: '', type: '' } },