(Mongo / Mon goose) Как обрабатывать ожидание результата нескольких запросов - PullRequest
0 голосов
/ 12 апреля 2020

Я пишу бот Discord, который генерирует еженедельную статистику гильдии для использования текстового и голосового каналов. Мой код делит несколько запросов Mon go на отдельные методы:

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 ]. Я уверен, что я не правильно использую обещания, но когда я следую документации Mon goose, он говорит мне использовать exec() вместо then(), но я получаю ошибку channels = null с этим.

Что-нибудь выпрыгивает кому-нибудь? Это похоже на довольно распространенную модель. У кого-нибудь есть решение, как разрешить несколько запросов Mon goose в одном методе?

Ответы [ 2 ]

1 голос
/ 12 апреля 2020

Promise.all должен принимать массив обещаний, в то время как ваши функции возвращают обычный массив, поэтому вам нужно вернуть весь запрос в вспомогательном методе, который получает пользователей и каналы, а затем выполнить лог c после 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
  });
}
0 голосов
/ 12 апреля 2020

У вас нет операторов возврата на уровне root ваших функций, поэтому они всегда синхронно возвращают 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
  })
}
...