(Mongo/Mongoose) 如何处理等待多个查询的结果
Posted
技术标签:
【中文标题】(Mongo/Mongoose) 如何处理等待多个查询的结果【英文标题】:(Mongo/Mongoose) How to handle waiting for the result of multiple queries 【发布时间】: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 查询?
【问题讨论】:
【参考方案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
语句。 topTextChannels
和 topVoiceMembers
都在打印正确的数据。
我已经编辑了我的答案,你现在可以检查一下吗?希望它现在有帮助
我重新组织了查找方法以返回 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
)
【讨论】:
以上是关于(Mongo/Mongoose) 如何处理等待多个查询的结果的主要内容,如果未能解决你的问题,请参考以下文章
如何处理:循环调用'Thread.sleep()',可能是忙等待