我正在使用NodeJS和Express,通过查询数据库在网页上动态生成HTTP。该页面将通过遍历MongoDB集合并使用数据库中的各种属性填充元素属性和内容来加载元素。 PUG / Jade允许迭代返回的Database JSON以生成元素
起初我只需要查询一个集合,但在需要查看两个或更多集合时遇到了麻烦。
我正在链接回调,但第一个查询中的数据卡在第一个闭包中。我切换到Github(https://github.com/request/request-promise)
上方便的请求 - 承诺框架我使用.then()子句,但我仍然丢失了返回值。我以为我可以运行res.render两次,但如果第二个数据库查询仍未定义,它不允许我生成部分网页。
router.get('/main', authorize.adminRequired, function(req, res, next) {
rp.get({
url: 'http://localhost:3000/menus'
}, function(err, response, menuItems) {
console.log(menuItems);
res.render('index', {menu: menuItems}) //PUG error, PUG variable "history" is undefined
}).then(rp.get({
url: 'http://localhost:3000/transactions'
}, function(err, response, transactions, menuItems) { //menuItems is now Undefined
console.log(transactions);
return res.render('index', {menu: JSON.parse(menuItems), history: JSON.parse(menuItems)});
}));
});
我设法更改代码以使其正常工作。以下代码似乎没问题。但有没有更好的方法来使用await写出来并传递该值,而不是将这些函数链接为新变量?我真的不知道如何使用Promise。
router.get('/main', authorize.adminRequired, function(req, res, next) {
var getMenuItems = rp.get({
url: 'http://localhost:3000/menus'
}, function(err, response, menuItems) {
console.log(menuItems);
return menuItems;
});
getMenuItems.then(function(result){
rp.get({
url: 'http://localhost:3000/transactions'
}, function(err, response, transactions) {
console.log(transactions);
return res.render('index', {menu: JSON.parse(result), history: JSON.parse(transactions)});
});
});
});
答案 0 :(得分:1)
首先,这段代码
}).then(rp.get({
是错误的,因为.then接受1(或2)个参数,但如果它们不是函数
,则默默地忽略它们(即不产生错误)像你一样使用.then,你传递调用 rp.get
的结果 - 这是一个Promise,而不是一个函数
所以,正确使用请求承诺:
router.get('/main', authorize.adminRequired, function(req, res, next) {
rp.get({
url: 'http://localhost:3000/menus'
})
.then(menuItems => rp.get({ url: 'http://localhost:3000/transactions'}).then(transactions => ({transactions, menuItems})))
.then(({transactions, menuItems}) => {
// now do whatever with transactions and menuItems
})
});
使用async / await
router.get('/main', authorize.adminRequired, async function(req, res, next) {
let menuItems = await rp.get({url: 'http://localhost:3000/menus'});
let transactions = await rp.get({ url: 'http://localhost:3000/transactions'});
// now do whatever with transactions and menuItems
});
答案 1 :(得分:0)
由于你的两个requests
不相互依赖,你可以利用Promise.all()
来让你并行而不是顺序地请求它们 - 并使代码更简单:
router.get('/main', authorize.adminRequired, function(req, res, next) {
Promise.all([
rp.get('http://localhost:3000/menus'),
rp.get('http://localhost:3000/transactions')
])
.then(([menus, transactions]) => {
// now you have menus and transaciotns
res.render(/* use menus and transactions */ )
})
})