Nodejs Await Doesn't Wait

Viewed 687

I have a simple MongoDbB example using await, but for some reason the code doesn't wait when I use the await keyword...

index.js:

require('dotenv').config()
const utilFunctions = require('./functions')

const getKeywords = utilFunctions.getKeywords

const main = async () => {

    const keywords = await getKeywords(process.env.MONGO_URI)

    console.log('keywords: ', keywords)

}

main()

and functions.js:

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

const getKeywords = async (uri) => {
    console.log('uri is: ', uri)

    MongoClient.connect(uri, function (err, db) {
        if (err) throw err;

        console.log('connected...')

        var dbo = db.db("eon-data")

        dbo.collection("twitter-keyword-scanner").find({}).toArray(function (err, mainDoc) {
            if (err) throw err;

            const keywords = mainDoc[0].config.keywordsToLookFor
            console.log('got keywords: ', keywords)
            db.close()
            return keywords
        })
    })
}


module.exports = {
    getKeywords
}

When I run node index.js I get this output:

uri is:  (my mongo uri)
(node:23990) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
keywords:  undefined
connected...
got keywords.  [
  (data in the db)
]

For some reason the async / await is not working...

It does indeed print the keywords in the log "got keywords:", but in index.js it is printing "keywords: undefined" and printing it before 'getKeywords' ever returns...

I would expect the console.log to happen after the function getKeywords returns, but actually it is being run beforehand. Am I doing something wrong here? Can anyone see why the async/await is not working properly?

thanks!

PS- you can find the full project here: https://github.com/JimLynchCodes/Ameritrader-Bots/tree/master/twitter-keyword-scanner

Running this with node v12.16.1

1 Answers

After I wrapped my entire callback in new Promise it finally worked properly:

functions.js:

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

const getKeywords = async (uri) => {
    console.log('uri is: ', uri)

    return new Promise((resolve, reject) => {

        MongoClient.connect(uri, function (err, db) {
            if (err) throw err

            console.log('connected...')

            var dbo = db.db("eon-data")

            dbo.collection("twitter-keyword-scanner").find({}).toArray(function (err, mainDoc) {
                if (err) throw err

                const keywords = mainDoc[0].config.keywordsToLookFor
                console.log('got keywords. ', keywords)
                db.close()
                resolve(keywords)
            })
        })
    })
}

After reading the mongo documentation for "MongoClient.connect" I can see that this connect function returns null and not a Promise... so I guess there is not really a way around wrapping it with "new Promise" (perhaps there is an alternative syntax to connect besides "MongoClient.connect" that returns a promise as it connects. If you know it please leave a comment!)

Related