为了使网页上的内容能够跟随数据库中记录的变化而变化,需要对静态网页绑定数据。数据绑定就是通过SQL查询读取数据库中的数据,将返回的查询结果嵌入到网页的指定元素中。Node.js数据绑定的过程分为2步:①在routes/index.js文件的路由处理函数中查询数据库并将查询结果发送给模板文件;②在页面的ejs模板文件中嵌入对应的变量。
1 首页的数据绑定
首页有多个栏目,对应多个查询结果。首页数据绑定的具体步骤如下:
1. 1 服务器端执行SQL 查询并返回数据
在routes/index.js文件中,对访问首页的路由添加如下创建查询的代码。
javascript
const mysql = require('./../database'); //引用连接数据库模块
router.get('/', function(req, res, next) { //首页的路由处理
var query = 'SELECT * FROM news ORDER BY ID DESC limit 6';
mysql.query(query, function(err, rows, fields){
var articles = rows;
console.log(articles); //输出articles到控制台,用于调试
res.render('index', { articles: articles }); //将articles发送给index模板
});
});
1.2 在模板文件中嵌入服务器端返回的数据
在index.ejs模板文件中嵌入数据。从图4-5可知,数组articles保存了第一个栏目的所有记录,所以要把articles数组通过遍历输出到第一个栏目的各个<li>标签中。为此,将index.ejs模板中第一个栏目中的如下ul元素代码:
html
<ul>
<% for(var i = 1, max = articles.length; i < max; i++) {%>
<li><a href="/show/<%= articles[i].ID %>"><%= articles[i].title %></a>
<span>[<%= articles[i].infotime %>]</span></li>
<% } %>
</ul>
2. 绑定多个栏目的数据
在routes/index.js文件中,添加对首页其他栏目创建查询的代码,并将所有查询的结果数据都发送给index模板。修改后的router.get()代码如下。
javascript
router.get('/', function(req, res, next) {
var query = 'SELECT * from news order by ID desc limit 6';
mysql.query(query, function(err, rows, fields) {
var articles = rows;
articles[0].content = articles[0].content.replace(/<[^>]*>?/gm, '').slice(0, 40);
articles.forEach(function(ele) {
ele.infotime = formatDate(ele.infotime);
});
const querystring = "船山科普"; //第2个栏目
qry2 = 'SELECT * from news where BigClassName=? order by ID desc limit 5';
mysql.query(qry2, [querystring], function(err, rows, fields) {
var kepu = rows;
kepu.forEach(function(ele) {
ele.infotime = formatDate(ele.infotime);
});
qry3 = 'SELECT * FROM wcszz ORDER BY ID DESC limit 3'; //第3个栏目
mysql.query(qry3, function(err, rows, fields) {
var zhuzuo = rows;
res.render('index', { articles: articles,kepu: kepu,zhuzuo: zhuzuo});
});
});
});
});
上述代码中,通过{articles:articles, kepu: kepu, zhuzuo: zhuzuo}输出3个json数组,对应3个栏目的数据。
提示:有几个栏目,就用mysql.query()执行几个查询,一个栏目就对应一个查询的记录集(recordset)。但要注意的是:这几个mysql.query()函数并不是同级的,而是嵌套的,第2个mysql.query()要嵌入到第1个mysql.query()中,第3个要嵌入到第2个之中。
3. 解决多个mysql.query()函数嵌套的问题
由于mysql.query()函数是异步函数,因此第2个mysql.query()要嵌入到第1个mysql.query()函数的回调函数中。如果要执行n个查询,就需要n个mysql.query()函数嵌套,代码可读性差,这称为回调地狱。为此,可以使用async函数让异步函数返回值,从而不需要回调函数。解决嵌套问题。代码如下:
javascript
const util = require('util');
const queryAsync = util.promisify(conn.query).bind(conn);
router.get('/', async function(req, res, next) {
var query = 'select * from news order by id desc limit 6';
var title = await queryAsync(query);
var query2 = "select * from news where BigClassName='学生工作' order by id desc limit 6";
var title2 = await queryAsync(query2);
res.render('lm', { title: title, title2: title2 });
});
这样就完美解决了mysql.query()函数嵌套的问题。