Skip to content
Advertisement

How to Wait Until a MongoDB Connection is Made before Using the Database

I have the following code to create a connection to my MongoDB database, and to store it for future use.

const mongodb = require('mongodb');
const MongoClient = mongodb.MongoClient;

// The database will be defined once a connection to between the cluster and mongodb is created
let _database;

const uri = '';
const databaseName = 'db';

const mongoConnect = () => {
    MongoClient.connect(uri)
        .then((client) => {
            _database = client.db(databaseName);
        })
        .catch((err) => {
            console.log(err);
            throw err;
        });
};

const getDb = () => {
    if (_database) {
        return _database;
    }
    throw 'No database found!';
};

module.exports = {
    mongoConnect,
    getDb
}

My problem is that _database is undefined until the connection is made. If my website tries to use the database before _database is defined it will throw an error and crash.

I want to make it so instead of crashing, other portions of my code would just wait until _database is not undefined. Sounds like a await/async solution is needed, but I can’t wrap my head around how to approach implementing something like that here. Any advice would be great!

Advertisement

Answer

First approach: To make mongoConnect an async function and await on it before any of the remaining code is executed.

const mongoConnect = async () => {
    try {
        const client = await MongoClient.connect(uri);
        _database = client.db(databaseName);
    } catch(e) {
        console.log(err);
        throw err;
    }
};

In the beginning of your code

await mongoConnect();
//Remaning code here

Second approach: To make getDb function await till database connection is available

const mongodb = require('mongodb');
const MongoClient = mongodb.MongoClient;

const uri = '';
const databaseName = 'db';

const databasePromise = new Promise((resolve, reject) => {
    MongoClient.connect(uri)
    .then((client) => {
        resolve(client.db(databaseName));
    })
    .catch((err) => {
        reject(err);
    });
})

const getDb = async () => {
    return await databasePromise;
};

module.exports = {
    getDb
}

Sample code for you to run and check the second approach:

const databasePromise = new Promise((resolve) => {
    console.log("Connecting to db in 5 seconds...")
    setTimeout(() => {
        console.log("Done")
        resolve("done")
    }, 5000)
})

const getDb = async () => {
    return await databasePromise;
};

console.time("First_getDb_call")
getDb().then(res => {
    console.timeEnd("First_getDb_call")
    console.log(res)
    console.time("Second_getDb_call")
    getDb().then(res => {
        console.timeEnd("Second_getDb_call")
        console.log(res)
    })
})
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement