【问题标题】:async separated queries in nodejs and mongoosenodejs和mongoose中的异步分离查询
【发布时间】:2018-09-04 10:04:25
【问题描述】:

我想使用 Mongoose 和 ajax 异步向 mongodb 查询两个不同且不同的东西。

代码如下:

var teams, faculties;
userModel.find({}).sort('-score').exec((err, result) => {
        teams = result;
    });

    userModel.aggregate([{
        "$group": {
            _id: "$faculty",
            average: {
                $avg: "$score"
            }
        }
    }]).exec((err, result) => {
        faculties = result;
    });
res.render('/scoreboard', {
    information: [teams, faculties]
})

是否有更好的实现来处理异步运行的查询?

【问题讨论】:

  • 这将失败,因为它会在数据库调用返回之前尝试同步调用res.render。要解决此问题,请将 res.render 部分移动到第二个回调中。更好的是,重写它,以便对数据库的两个调用并行运行。由于它们是使用回调完成的,因此您可以使用名为 async 的 npm 库来组合它们。或者,您可以将它们包装在 Promise 中并使用 Promise.all 组合它们。
  • @DavidKnipe 你能给我一些关于如何实现的提示吗?感谢您的有用评论。
  • 这两种调用银行的方法是在一个函数内吗?在请求中,响应?我需要更多代码来为您提供答案。

标签: node.js express mongoose


【解决方案1】:

使用async/await,我们消除了回调并使调用保持独立。错误特征也可以通过将 if 与否定条件放在一起来简化。

app.get('/myroute', async(req, res) => {
    try {
        const teams = await userModel.find({}).sort('-score')
        const faculties = await userModel.aggregate([{
            "$group": {
                _id: "$faculty",
                average: {
                    $avg: "$score"
                }
            }
        }])    
        res.render('/scoreboard', { information: [teams, faculties] })

    } catch (error) {
        res.status(400).send(error)
    }
})

【讨论】:

  • @Li357 谢谢,如果我做了一个简单的处理,但在异步的情况下,需要多次尝试,每次调用银行一次,否则会收到解构错误。跨度>
  • 当我console.log(teams) 时它无法正常工作,它返回的数据字符串对我来说听起来模棱两可
  • @MostafaGhadimi 您能否将该结果添加到问题中?供我分析。我认为它与sort()有关。查找必须返回所有数据。
  • 这将使两个数据库调用串联运行。如果您希望它们使用 async/await 语法并行运行,请尝试以下操作:const teamsPromise = userModel.find({}).sort('-score'); const facultiesPromise = userModel.aggregate( ... ); const teams = await teamsPromise; const faculties = await facultiesPromise; res.render('/scoreboard', { information: [teams, faculties] });
【解决方案2】:

可以进行的另一项改进是使用Promise.all 并行运行它,因为这些功能彼此独立。

app.get('/myroute', async(req, res) => { 
    const response = await Promise.all([
      userModel.find({}).sort('-score'),
      userModel.aggregate([{
          "$group": {
              _id: "$faculty",
              average: {
                  $avg: "$score"
              }
          }
      }])    
    ]); // response will return as [teams, faculties]
    res.render('/scoreboard', { information: response })
})

【讨论】:

  • Promise.all 并没有神奇地让 Promise 运行“并行”... Promise 像通常那样异步运行,Promise.all 只是将它们组合成一个 Promise,当所有 Promise 都解决时解决...
  • @Li357 很好的反馈,我可能用了错误的词来描述它。谢谢。
  • @Li357 你的意思是它不能异步工作?
  • @deerawan 它可以工作,但我怎样才能访问它们的平均值?当我 console.log(response) 它包含 userModel.find({}) 的数据和一个对象数组:i.stack.imgur.com/7v1XT.png
  • Li357 对此不太清楚:“Promise.all 不会神奇地让承诺运行“并行”-我不认为他们的意思是说它不会运行在平行下。两个异步任务将几乎同时启动,并且它们将并行运行。可能 Li357 意味着即使您没有将它们包裹在 Promise.all[ ... ]) 中,它们也会并行运行。
猜你喜欢
  • 1970-01-01
  • 2020-05-06
  • 2021-04-08
  • 2017-09-05
  • 2016-08-12
  • 1970-01-01
  • 2020-01-31
  • 2019-10-21
相关资源
最近更新 更多