【问题标题】:(Mongo/Mongoose) How to handle waiting for the result of multiple queries(Mongo/Mongoose) 如何处理等待多个查询的结果
【发布时间】:2020-07-24 16:12:12
【问题描述】:

我正在编写一个 Discord 机器人,它会为文本和语音频道的使用情况生成每周公会统计数据。我的代码将几个 Mongo 查询分成不同的方法:

function getTopActiveTextChannels() {
  let topTextChannels = []
  ChannelModel.find({}).sort({"messageCountThisWeek": -1}).limit(topLimit)
   .exec(channels => {
    channels.forEach(c => {
      topTextChannels.push({"name": c.name, "messageCount": c.messageCount})
    })
    console.log(topTextChannels)
    return topTextChannels
  })
}

function getTopActiveVoiceMembers() {
  let topVoiceMembers = []
  UserModel.find({}).sort({"timeSpentInVoice": -1}).limit(topLimit)
  .exec(users => {
    users.forEach(u => {
      topVoiceMembers.push({"username": u.username, "timeSpentInVoice": u.timeSpentInVoice})
    })
    console.log(topVoiceMembers)
    return topVoiceMembers
  })
}

然后我有一种方法可以同时调用它们,并且(现在)将值打印到控制台:

function getWeeklyGuildStats(client) {
  let topActiveTextChannels = getTopActiveTextChannels()
  let topVoiceMembers = getTopActiveVoiceMembers()
  let promisesArray = [topActiveTextChannels, topVoiceMembers]

  Promise.all(promisesArray).then(values => {console.log(values)})
}

执行getWeeklyGuildStats(client) 输出:[ undefined, undefined ]。我确定我没有正确使用 Promise,但是当我按照 Mongoose 的文档进行操作时,它告诉我使用 exec() 而不是 then(),但我得到了 channels = null 错误。

有什么东西会跳出来吗?这似乎是一个相当普遍的模式。有没有人可以解决如何在一个方法中解决多个 Mongoose 查询?

【问题讨论】:

    标签: javascript mongodb mongoose discord


    【解决方案1】:

    Promise.all 应该接受一个 promise 数组,而你的函数返回的是普通数组,所以你需要在获取用户和频道的辅助方法中返回整个查询,然后在 promise.all

    你的函数可能看起来像这样

    function getTopActiveTextChannels() {
      return ChannelModel.find({}).sort({"messageCountThisWeek": -1}).limit(topLimit).exec();
    }
    
    function getTopActiveVoiceMembers() {
      return UserModel.find({}).sort({"timeSpentInVoice": -1}).limit(topLimit).exec();
    }
    

    那么调用这两个方法的函数将类似于

    function getWeeklyGuildStats(client) {
      let topActiveTextChannels = getTopActiveTextChannels()
      let topVoiceMembers = getTopActiveVoiceMembers()
      let promisesArray = [topActiveTextChannels, topVoiceMembers]
    
      Promise.all(promisesArray).then(values => {
         console.log(values);
         // here you could do your own logic, the for loops you did in the helper methods before
      });
    }
    

    【讨论】:

    • 好的,将参数修改为Promise.all() 为方法调用。仍然得到输出[ undefined, undefined ]
    • 你能在查询完成后尝试 console.log 用户和频道吗?我的意思是在 .then 之后在 getTopActiveVoiceMembers 函数中记录用户,对于频道也是如此?
    • 我在每个方法的返回值之前添加了console.log 语句。 topTextChannelstopVoiceMembers 都在打印正确的数据。
    • 我已经编辑了我的答案,你现在可以检查一下吗?希望它现在有帮助
    • 我重新组织了查找方法以返回 Mongoose 承诺,并将 .then() 逻辑移动到单独的辅助方法,我从主方法调用。谢谢,成功了!
    【解决方案2】:

    您的函数的根级别中没有任何返回语句,因此它们总是同步返回undefined。我不熟悉您正在使用的库,但是如果例如 ChannelModel.find({}).exec(callback) 返回一个返回值为 callback 的承诺,正如您的代码所暗示的那样,那么您只需要在您的函数中添加一个 return 语句.

    例如:

    function getTopActiveTextChannels() {
      let topTextChannels = []
      // Return this! (Assuming it returns a promise.) Otherwise you're always returning `undefined`.
      return ChannelModel.find({}).sort({"messageCountThisWeek": -1}).limit(topLimit)
       .exec(channels => {
        channels.forEach(c => {
          topTextChannels.push({"name": c.name, "messageCount": c.messageCount})
        })
        console.log(topTextChannels)
        return topTextChannels
      })
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-30
      • 1970-01-01
      • 2012-10-28
      • 2014-03-03
      • 2019-04-02
      • 1970-01-01
      • 1970-01-01
      • 2020-11-25
      相关资源
      最近更新 更多