3

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

Jim
  • 3,821
  • 1
  • 28
  • 60
  • Because `getKeywords` not returning promise – Ashh Mar 28 '20 at 04:34
  • ok... think one thing if you are using `async` in `getKeywords`, did you use `await` inside it? No, why? Because there is nothing inside that function which is returning `Promise`. So simply if the function is not returning promise then you have to make it to behave it like that using `new Promise()` syntax. – Ashh Mar 28 '20 at 04:40
  • I don't understand. Can you please submit a full answer – Jim Mar 28 '20 at 04:44
  • 1
    I understand what you are saying, but I cannot get a working solution... – Jim Mar 28 '20 at 04:46

1 Answers1

0

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!)

Jim
  • 3,821
  • 1
  • 28
  • 60
  • I thought the whole point of async/await was to avoid having to wrap everything in `new Promise` though... – Jim Mar 28 '20 at 04:50
  • That is what I was saying. and you do not need to use `async` if the function already returning `promise`. – Ashh Mar 28 '20 at 04:56
  • I would prefer to use async/ await to `new Promise`. Can you please give me the solution using this syntax... – Jim Mar 28 '20 at 05:04
  • It would be good to use promises directly for the database operations. There is plenty of documentation in mongodb on how to use promises for all of its database operations. I'd suggest you go look that up in the documentation and then come back if/when you get stuck on something. – jfriend00 Mar 28 '20 at 10:27