JusteThom
JusteThom

Reputation: 120

Finally block execute before the end of try block

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

Answers (2)

AlexZeDim
AlexZeDim

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

user13862726
user13862726

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

Related Questions