[英]Express/NodeJS multiple mysql queries for the same route
在一个用express / nodejs编写的博客中,我试图在单个文章页面中同时显示该文章(工作正常)和一组2篇推荐文章。 不幸的是,正如您在代码的注释位中看到的那样,它不起作用(无法两次渲染同一模板)
在这种情况下最好的方法是什么?
<!-- language: lang-js -->
router.get('/*', function(req, res, next) {
var slug=req.url.replace(/^\//,'').replace(/\/$/,'');
var bg = getRandomInt(5);
if(slug==''){
connection.query('SELECT * FROM `pages` WHERE NOT slug = "about"', function (error, results, fields) {
res.render('index', { title: title, year: year, bg:bg, pages: results });
});
}else{
connection.query('SELECT * FROM `pages` where slug=?', [slug], function (error, results, fields)
{
if(results.length){
res.render('page', { title: results[0].title, page:results[0] });
}else{
console.log(req);
res.render('error',{url: 'http://'+req.headers.host+req.url});
}
});
/* not working apparently you can't send the header of the template twice umhh
connection.query('SELECT * FROM `pages` ORDER by RAND () LIMIT 2', function (error, random, fields)
{
res.render('page', { pages:random});
});
*/
}
});
您不能两次渲染页面,否则会出现错误:将标头发送到客户端后无法设置标头
您需要做的是获取当前文章和推荐的页面,并在获得两个查询的结果后呈现该页面。
为了实现这一点,我使用了: Promise.all
,然后执行了一个res.render
router.get('/*', async (req, res, next) => {
const slug = req.url.replace(/^\//, '').replace(/\/$/, '');
const bg = getRandomInt(5);
if (slug == '') {
const results = await query('SELECT * FROM `pages` WHERE NOT slug = "about"');
return res.render('index', {
title: title,
year: year,
bg: bg,
pages: results
});
}
// Get current article and recommended pages
// Promise.all returns an array where each entry has
// the resolved value of the promise passed at that index
const [article, recommended] = await Promise.all([
query('SELECT * FROM `pages` where slug=?', [slug]),
query('SELECT * FROM `pages` ORDER by RAND () LIMIT 2')
]);
if (article.length) {
// Render the article & recommended pages at once.
res.render('page', {
title: article[0].title,
page: article[0],
pages: recommended
});
} else {
console.log(req);
res.render('error', {
url: 'http://' + req.headers.host + req.url
});
}
});
// Query helper
// You can use promisify...
function query(statement, placeholders = []) {
return new Promise((resolve, reject) => {
connection.query(query, placeholders, (error, results) => {
if(err)
return reject(err);
resolve(results);
});
});
}
您现在拥有的方式
根据您的预期进行了更新。 请注意,这会使查询顺序成为顺序,这可能是不希望的。 您将要使用async
库来帮助管理同时运行它们和仍然合并结果:
router.get('/*', (req, res, next) => {
const slug = req.url.replace(/^\//, '').replace(/\/$/, '');
const bg = getRandomInt(5);
if (slug == '') {
return connection.query('SELECT * FROM `pages` WHERE NOT slug = "about"', (error, results, fields) => {
res.render('index', { title: title, year: year, bg: bg, pages: results });
});
} else {
return connection.query('SELECT * FROM `pages` where slug=?', [slug], (error, results, fields) => {
if (results.length) {
return connection.query('SELECT * FROM `pages` ORDER by RAND () LIMIT 2', (error, random, fields) => {
if (error) {
// handle error
}
// consolidate renders into a single call
// adjust the template file accordingly
return res.render('page', { title: results[0].title, page: results[0], pages: random });
});
} else {
console.log(req);
return res.render('error', { url: 'http://' + req.headers.host + req.url });
}
});
}
});
或者,考虑使用bluebird
& async
/ await
,这只是另一种样式-为您提供基于节点8+的新选项。 在这一查询中,查询再次在同一时间开始。
const bluebird = require('bluebird');
router.get('/*', async (req, res, next) => {
try {
const slug = req.url.replace(/^\//, '').replace(/\/$/, '');
const bg = getRandomInt(5);
if (slug == '') {
const results = await bluebird.fromCallback(cb => connection.query('SELECT * FROM `pages` WHERE NOT slug = "about"', cb));
return res.render('index', { title: title, year: year, bg: bg, pages: results });
} else {
const [results, random] = await Promise.all([
bluebird.fromCallback(cb => connection.query('SELECT * FROM `pages` where slug=?', [slug], cb)),
bluebird.fromCallback(cb => connection.query('SELECT * FROM `pages` ORDER by RAND () LIMIT 2', cb))
]);
if (results && results.length) {
return res.render('page', { title: results[0].title, page: results[0], pages: random });
} else {
return res.render('error', { url: 'http://' + req.headers.host + req.url });
}
}
} catch (e) {
return res.render('error', { url: 'http://' + req.headers.host + req.url });
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.