我正在使用Node.js和猫鼬,但是这个问题纯粹是关于async
await
部分。我写了这段代码,它可以正常工作。
router.get('/applications/:_id', async (req, res, next) => {
var posting = await Posting.findOne({'_id': req.params._id, 'creatorId': req.user._id, 'visible': true}); // await here
var seekers = await Account.find({'accType': 'seeker', 'blocked': false});
console.log(posting.applications) // no await here
// ^^^ this will log the applications array.
res.render('users/employer/applications', {
user: req.user,
title: 'Job applications',
applications: posting.applications,
seekers: await seekers,
})
});
但是,如果我这样做:
router.get('/applications/:_id', async (req, res, next) => {
var posting = Posting.findOne({'_id': req.params._id, 'creatorId': req.user._id, 'visible': true}); // remove await from here
var seekers = Account.find({'accType': 'seeker', 'blocked': false});
console.log(await posting.applications); // add await here
// ^^^ this will log undefined
res.render('users/employer/applications', {
user: req.user,
title: 'Job applications',
applications: await posting.applications,
seekers: await seekers,
})
});
我无法打印出
posting.applications
数组。 (未定义)。但是我可以像这样打印出整个对象:
router.get('/applications/:_id', async (req, res, next) => {
var posting = Posting.findOne({'_id': req.params._id, 'creatorId': req.user._id, 'visible': true});
// ^^^ remove await from here
var seekers = Account.find({'accType': 'seeker', 'blocked': false});
console.log(await posting); // add await here
// ^^^ this will log the object
console.log(await posting.applications); // this will log undefined
res.render('users/employer/applications', {
user: req.user,
title: 'Job applications',
applications: await posting.applications,
seekers: await seekers,
})
});
我以为,等待会停止执行代码,直到代码执行完毕。那么,如果对象存在,为什么我无法获得属性?
[重复说明]我也在通过将对象发送到视图来检查这一点。它在视图中的行为与console.log中的行为相同。这是一个简化的示例。
最佳答案
在第一个示例中:
var posting = await Posting.findOne({'_id': req.params._id, 'creatorId': req.user._id, 'visible': true}); // await here
var seekers = await Account.find({'accType': 'seeker', 'blocked': false});
您正在等待
Posting.findOne
和Account.find
返回的诺言,并将这些诺言的分辨率值存储在posting
和seekers
中。在第二个示例中:
var posting = Posting.findOne({'_id': req.params._id, 'creatorId': req.user._id, 'visible': true}); // remove await from here
var seekers = Account.find({'accType': 'seeker', 'blocked': false});
console.log(await posting.applications); // add await here
...您正在将承诺对象本身存储在
posting
和seekers
中,然后从applications
中的承诺中获取属性posting
。承诺没有名为applications
的属性,因此posting.applications
会导致undefined
。 await
输入非承诺值会返回值本身,因此await posting.applications
为您提供undefined
。在您的第三个示例中:
var posting = Posting.findOne({'_id': req.params._id, 'creatorId': req.user._id, 'visible': true});
// ^^^ remove await from here
var seekers = Account.find({'accType': 'seeker', 'blocked': false});
console.log(await posting); // add await here
...您再次将诺言存储在
posting
中,但是在执行日志时会等待该诺言,因此分辨率值进入console.log
。但是posting
仍然指的是诺言,而不是其结果,因此posting.applications
仍然是undefined
。在第三个示例中,您可以执行以下操作:
posting = await posting;
...但实际上,您的第一个例子很好。
但是,如果希望
Posting.findOne
和Account.find
重叠,则可以使用Promise.all
:var [posting, seekers] = await Promise.all([
Posting.findOne({'_id': req.params._id, 'creatorId': req.user._id, 'visible': true}),
Account.find({'accType': 'seeker', 'blocked': false})
]);
关于javascript - 使用异步等待时无法获取对象的属性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51442451/