Search code examples
node.jsfor-loopmongoosestellar

NodeJS Async/Await doesn't await (returns Promise pending)


I'm writing an API that gets past transactions on the Stellar network for a user, looks up the corresponding users in my database, and put's it all together into a JSON (to respond to the request - later).

Problem: looking up the username corresponding to the accountID ("from" field) is an async method with mongoose and only returns data after the JSON has been assembled.

I've tried to use async/await, promises, .thens but nothing seems to work.

server.payments()
    .forAccount(accountId)
    .cursor('now')
    .order('desc')
    .limit(2)
    .call()
    .then(function (page) {
        var history = []
        for(var i = 0; i<page.records.length; i++){
            var obj = page.records[i]
            //Get the username corresponding to the key from my database
            //FIXME
            var username
            findUser(obj["from"]).then(result => {
                username = result
            })
            var payment = {
                "currency":obj["asset_code"],
                "from": obj["from"],
                "username":username,
                "amount": obj["amount"],
                "timestamp":obj["created_at"]
            }
            history.push(payment)
        }
        console.log(history)
        //console.log(JSON.stringify(history))
    })
    .catch((err) => {
        console.log(err)
    })

async function findUser(senderKey){
    var user = await mongoose.User.findOne({publicKey: senderKey})
    console.log(user.username)
    return user.username
}

Expected result: findUser returns value, payment variable uses it and gets logged together.

What happens: findUser starts looking for data, payment variable gets put together (username as undefined) and logged, findUser returns data.

Here's the log: (spiderman is the actual username from my database)

[ { currency: 'MEUR',
    from: 'GACRQARPR2OMWRG6IH7HM5DYTA3FMM6UKA7NKS4BIJIADRIKFRPAIE7G',
    username: undefined,
    amount: '3.0000000',
    timestamp: '2019-05-07T13:37:04Z' },
  { currency: 'MEUR',
    from: 'GACRQARPR2OMWRG6IH7HM5DYTA3FMM6UKA7NKS4BIJIADRIKFRPAIE7G',
    username: undefined,
    amount: '2.0000000',
    timestamp: '2019-05-07T13:34:21Z' } ]
spiderman
spiderman

Solution

  • You can use the new "for of" loop along with async await :-

    server.payments()
        .forAccount(accountId)
        .cursor('now')
        .order('desc')
        .limit(2)
        .call()
        .then(async function (page) {
            var history = []
    
            for(const obj of page.records) {
              const username = await findUser(obj["from"]);
                var payment = {
                    "currency":obj["asset_code"],
                    "from": obj["from"],
                    "username":username,
                    "amount": obj["amount"],
                    "timestamp":obj["created_at"]
                }
                history.push(payment)
            }
    
            console.log(history)
            //console.log(JSON.stringify(history))
        })
        .catch((err) => {
            console.log(err)
        })