使用异步等待时无法获取对象的属性

时间:2018-07-20 12:20:59

标签: javascript node.js asynchronous async-await

我正在使用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,
    })
});

我认为await会停止执行代码,直到代码执行完毕。那么,如果对象在那里,为什么我无法获得属性?

[重复说明]我也在通过将对象发送到视图来进行检查。它在视图中的行为与console.log中的行为相同。这是一个简化的示例。

1 个答案:

答案 0 :(得分:2)

在您的第一个示例中:

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.findOneAccount.find返回的诺言,并将这些诺言的分辨率值存储在postingseekers

在第二个示例中:

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

...您要将 promise对象本身存储在postingseekers中,然后从{{ 1}}。承诺没有名为applications的属性,因此posting会产生applicationsposting.applications输入非承诺值会返回该值本身,因此undefined给您await

在您的第三个示例中:

await posting.applications

...您再次将 promise 存储在undefined中,但是在执行日志时要等待该承诺,因此 resolution值 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

...但实际上,您的第一个示例很好。

但是,如果您希望undefinedposting = await posting; 重叠,则可以使用Posting.findOne

Account.find