[英]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.