Reputation: 120
Context :
I have a discord bot running on discord.js and I recently created a MongoDB database to store some elements that I could use sometime in the futur. I want to retrieve all the members of a specific discord "guild" and put them into individual MongoDB documents.
What I do :
First, I fetch those members with :
const members = await testGuild.members.fetch();
This returns me a "Discord.Collection" object which is essentially a Map object.
Then I connect to my MongoDB using mongoose and I create a new document for each member of my members collection using :
await mongo().then(async mongoose => {
try {
members.each(async member => {
const {user} = member
await discordUserSchema.findOneAndUpdate({
_id: user.id
}, {
_id: user.id,
username: user.username,
discriminator: user.discriminator,
avatar: user.avatar,
bot: user.bot
}, {
upsert: true
});
});
} finally {
mongoose.connection.close();
}
});
My problem is that the finally block is executing before my try block is finished and I get this error :
(node:25008) UnhandledPromiseRejectionWarning: MongoError: server is closed
If I remove the try/finally blocks, I don't have any errors and the documents are correctly added to my collection but this is not the right way...
I also tried to connect to my database inside my each loop but it's awful because it opens then closes a connection for each member that I add to the collection and eventually, I get a timeout error.
What am I missing right here? Why the finally block executes this soon? Is that because of the async function inside my loop? How can I handle this differently?
Thanks.
Upvotes: 1
Views: 986
Reputation: 4352
The problem is in .each
function of discord.js
, which is a copy of .forEach
and won't wait, you might saw a relevant case in this question, for example.
So, to solve your problem with try/catch/finally
and synchronous code, you'll need to use:
for (const member of members) {
/**
* your async/await logic
* if you want it one by one
*/
}
or
await Promise.all(members.map(async member => {
/**
* await logic here
* if you want all at once in parallel
*/
}));
And as mentioned before. If your application creates the connection with MongoDB just once at the start, don't open/close a new one for each time when you need something from the DB, just use the old one.
Upvotes: 2
Reputation:
This article will help you out.
TLDR; Don't use try catch in that .then()
, just use the catch
and finally
already usable with the .then()
Upvotes: 0