Nodejs - 此代码中的执行顺序是什么?异步等待循环内部

时间:2017-08-16 16:04:52

标签: node.js express mongoose async-await

假设我们有一个模型“用户”和一个模型“游戏”。

一个用户可以拥有多个游戏,但一个游戏只属于一个用户。

在“用户”模型中,我们有字段“gamesCount” - 用户拥有的游戏总数

在“游戏”模型中,我们有字段userId - 与用户相关

现在我们需要遍历所有用户,并且对于每个用户,我们查询“游戏”集合以获取用户拥有的游戏数量,然后将值“gamesCount”保存到用户模型。

我有两段代码:

updateUserGamesCount: async function (req, res) {
    try {
        let users = await User.find({});
        for (let user of users) {
            user.gamesCount= await Game.count({userId: user._id});
            await user.save();
        }
        return res.status(200).send("Success");
    } catch (err) {
        res.status(500).send(err);
    }
}

此第1段不起作用。它只是加载一段时间然后请求超时。当我尝试修改gamesCount值以查看它是否已更新时,则在第1次代码段运行后,该值不会更新。

updateUserGamesCount: async function (req, res) {
    try {
        let users = await User.find({});
        for (let user of users) {
            user.gamesCount= await Game.count({userId: user._id});
            user.save();
        }
        return res.status(200).send("Success");
    } catch (err) {
        res.status(500).send(err);
    }
}

这第二个片段有效。唯一的区别在于第二个片段,我在user.save();

之前删除了await

为什么会这样?我认为user.save()是异步的,我们需要使用await?这些代码行的执行顺序究竟是什么?

非常感谢。

1 个答案:

答案 0 :(得分:2)

问:为什么第一个代码段工作而不是另一个?

A:我认为我们需要明确“它有效”的定义。它工作,因为没有错误被抛出?

我怀疑您的第二个代码段完全不起作用,而您只是通过删除await关键字来屏蔽错误。

第一个示例有效,因为您在继续之前等待save操作完成,如果抛出exception,则它会被try块捕获。而第二个代码不再等待save()响应返回,只是返回success

如果这个理论成立,那么任何事都不应该saved成功。无论是否有效,只有数据库可以说实话。第一个代码片段是正确的方法,但它可以在性能方面做得更好。

考虑捆绑所有save承诺,并为可能的性能增益做promise.all(...)。或者,在某些用例中,执行包含所有修改的一个save操作也是一个不错的选择。

请参阅:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all