Javascript (Mongo/Mongoose)如何处理多个查询结果的等待

Javascript (Mongo/Mongoose)如何处理多个查询结果的等待,javascript,mongodb,mongoose,discord,Javascript,Mongodb,Mongoose,Discord,我正在写一个Discord机器人,它可以为文本和语音频道的使用生成每周的公会统计数据。我的代码将几个Mongo查询划分为不同的方法: function getTopActiveTextChannels() { let topTextChannels = [] ChannelModel.find({}).sort({"messageCountThisWeek": -1}).limit(topLimit) .exec(channels => { channels.forE

我正在写一个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)})
}
执行
getWeeklyBuilderStats(客户端)
输出:
[未定义,未定义]
。我确信我没有正确使用承诺,但当我遵循Mongoose的文档时,它告诉我使用
exec()
而不是
then()
,但我得到了一个
channels=null
错误


有什么事让人吃惊吗?这似乎是一种相当普遍的模式。有没有人能在一个方法中解决多个Mongoose查询的问题?

承诺。所有的
都应该有一个承诺数组,而你的函数都返回普通数组,所以你需要在helper方法中返回整个查询,以获取用户和频道,然后在
承诺之后执行逻辑。全部

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

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
  });
}

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

例如:

函数getTopActivateXTChannels(){ 让topTextChannel=[] //返回这个!(假设它返回一个承诺。)否则您总是返回“未定义”。 返回ChannelModel.find({}).sort({“messageCountThisWeek”:-1}).limit(topLimit) .exec(频道=>{ channels.forEach(c=>{ 推送({“name”:c.name,“messageCount”:c.messageCount}) }) console.log(TopTextChannel) 返回TopTextChannel }) }
OK,将参数修改为
Promise.all()
作为方法调用。仍在获取输出
[undefined,undefined]
完成查询后,您是否可以尝试console.log用户和频道?我的意思是在之后记录用户。然后在getTopActiveVoiceMembers函数中,对通道也一样?我在每个方法的返回值之前添加了
console.log
语句。
topTextChannel
topVoiceMembers
都在打印正确的数据。我已经编辑了我的答案,你现在可以检查一下吗?,希望现在能有所帮助。我已经重新组织了我的查找方法,以返回Mongoose承诺,并将
.then()
逻辑移到了单独的助手方法,我从主方法调用了这些方法。谢谢,这就成功了!