我在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 */});
});
正如我在评论块中所写,我想:执行第一个选择查询,从行对象保存数据,执行第二个查询,再次将接收到的数据保存在其他对象中,然后最终渲染页面传递来自两个查询的数据。我的问题是,最好的方法是什么?
我知道匿名函数导致了一个问题。我已经尝试将问题解决了五个多小时,如下所示:
我还想创建"子页面"包含 student 页面的部分,它只需要来自一个查询的变量。另一个想法是使用 db , req , res 或 app 对象的其他一些功能。但是,正如我之前所说,我是Express的新人,我不知道如何实现我的上述想法。
请注意,连接表是不可能的 - 事实上,我想制作4-5个查询,然后渲染我的视图。我使用的是SQLite3数据库。
非常感谢你的帮助!我希望你能帮助我解决我的问题。
答案 0 :(得分:15)
在您的情况下,我会将数据库调用拆分为单独的调用,并使用next
中间件函数。
它看起来像是:
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);
当您获得/student
时,请先拨打findStudent
。 db调用完成后,它将呈现错误页面,或调用next()。接下来调用下一个函数findGroups
,然后调用renderStudentsPage
。在向下移动函数时,可以将数据存储在req对象上。
希望这会有所帮助,这里有更多信息: http://expressjs.com/guide/using-middleware.html
编辑/注:
我之前没有提到它,但是如果你在调用next()
时传入一个参数,你将触发错误处理状态。除非遇到错误实例,否则约定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();
});
}
然后在代码的其他地方,您可以处理渲染错误页面。
答案 1 :(得分:0)
我知道这是一个老问题,但对于任何仍然遇到问题并使用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: ''
}
},