How to return object from MongoDb database in findOne method

sorry if it’s easy mistake, I’ve not so much experience in JS, I’ve tried a lot of ways and I can’t resolve this problem.

I can find and print my object from database, but I can’t return it to my main method.

My main method (it’s in another file than methods to database):

(async () => {
    try{
        const someClass = new SomeClass();
        const object = await someClass.database.getFirstObjectFromBase("collectionName");
        console.log(object);
    } catch (err) {
        console.log(err);
    }
})();

and (before tries to debug this) my “object” is undefined. Take a look on two methods I’ve used:

async connectAndReturnWithFunction(func) {
    return new Promise(
        function(resolve, reject){
            mongoClient.connect(url, {}, (error, client) => {
                if (error) {
                    console.log("Cannot connect to db");
                } else {
                    console.log("Database connection established: " + dbname);
                };    
                const db = client.db(dbname);
                return func(db);
            }
        );
        }
    )
}

and last:

async getFirstObjectFromBase(collection) {
    return await this.connectAndReturnWithFunction(function(db) {
        return db.collection(collection)
        .findOne({}, function(err, result) {
            console.log(result);
            return result;
        })
    })
}

I tried something with ‘then’ too:

async getFirstObjectFromBase(collection) {
    return await this.connectAndReturnWithFunction(function(db) {
        return db.collection(collection)
        .findOne({})
        .then(result => {
            console.log(result); 
            return result;
        });
    })
}

In both examples of getFirstObjectFromBase console.log(result) print good object, but program just stop after this and I can’t return this JSON to main method.

Thank you in advice 🙂

Answer

Problems in your code:

  • Inside connectAndReturnWithFunction function, you never call resolve()

  • async functions always return a Promise, so you don’t need to create one yourself using the Promise constructor. You never use await keyword inside connectAndReturnWithFunction function, so making it async is unnecessary.

  • Inside connectAndReturnWithFunction function, inside the the callback function of mongoClient.connect, in case of an error, you log a message indicating that connection to database couldn’t be established but the last two lines of code

    const db = client.db(dbname);
    return func(db);
    

    will still execute. You probably meant to add those two lines inside the else block.

    mongoClient.connect(url, {}, (error, client) => {
        if (error) {
            console.log("Cannot connect to db");
        } else {
            console.log("Database connection established: " + dbname);
    
            const db = client.db(dbname);
            return func(db);
        }                 
    }
    

Reasone why object is undefined because inside the connectAndReturnWithFunction, you never call resolve(), which is needed to resolve the Promise with the data from the database.

To fix the problem, pass the resolve() and reject() functions to the callback function of connectAndReturnWithFunction function.

return func(db);

to

func(db, resolve, reject);

and inside the getFirstObjectFromBase function, call the resolve() function, passing in the result as an argument. In case of an error, call the reject() function, passing in the error object as an argument.

async getFirstObjectFromBase(collection) {
   return this.connectAndReturnWithFunction(function(db, resolve, reject) {
       return db.collection(collection)
         .findOne({}, function(err, result) {
             if (err) {
                reject(err);
             } else {
                resolve(result);
             }
         })
   })
}