1

I'm using node module mongodb v3.2.7, and using express to implement my api

I use callback. And, it works well

The function findItem

const findItem = function (id, callback) {
  if (db) {
    const collection = db.collection('transaction')
    collection.find({ user_id: id})
      .project({ ready: 1, online: 1, status: 1})
      .toArray(function (err, docs) {
        if (err) {
          callback(err)
        } else {
          callback(null, docs)
        }
      })
  }
}

My api

app.get('/', (req, res) => {
  try {
    if (req.query.user_id) {
      const contentType = 'application/json'

      res.set({ 'Access-Control-Allow-Origin': '*',
        'Content-Type': contentType })

      const user_id = parseInt(req.query.user_id, 0)
      findItem(user_id , function (err, docs) {
        if (err) {
          res.status(500).end()
          return res.send(err)
        }
        const data = processData(docs)
        console.log('data', data)
        return res.send(data)
      })
    } else {
      res.send()
    }
  } catch (ex) {
    console.log(ex)
  }
})

Then, I tried to use async/await instead of callback. But, it doesn't work. What mistake I did?

Function findItemAsyncAwait

const findItemAsyncAwait = async function (id) {
  if (db) {
    const collection = db.collection('transaction')
    var docs = await collection.find({ user_id: id })
      .project({ ready: 1, online: 1, status: 1})
      .toArray()
    return docs
  }
}

My changed api

app.get('/', (req, res) => {
  try {
    if (req.query.user_id) {
      const contentType = 'application/json'

      res.set({ 'Access-Control-Allow-Origin': '*',
        'Content-Type': contentType })

      const user_id = parseInt(req.query.user_id, 0)
      const promiseDocs = findItemAsyncAwait(user_id)
      promiseDocs.then((docs) => {
        console.log('docs', docs) // <= docs [], docs is an empty array without any document
        const data = processData(docs)
        console.log('data', data)
        return res.send(data)
      }).catch((err) => {
        res.status(500).end()
        return res.send(err)
      })
    } else {
      res.send()
    }
  } catch (ex) {
    console.log(ex)
  }
})

I still got stuck on this problem. Could anyone help?

Vu Le Anh
  • 708
  • 2
  • 8
  • 21

1 Answers1

1

You have to wait the collection

const findItemAsyncAwait = async function (id) {
  if (db) {
    return await db.collection('transaction')
      .find({ user_id: id })
      .project({ ready: 1, online: 1, status: 1})
      .toArray()
  }
}
Andrea Franchini
  • 548
  • 4
  • 14
  • This not only doesn't work, but also raise `eslint` warning `Redundant use of await on a return value`. The `docs` still is an empty array – Vu Le Anh Jul 31 '19 at 14:51
  • The eslint warning is correct most of the times - it should be a direct `return db.collection()` and the function can be declared without `async` - [more info here](https://stackoverflow.com/questions/44806135/why-no-return-await-vs-const-x-await). For what concern the functionality, `db.collection()` used without callback should behave like a Promise. – Andrea Franchini Aug 01 '19 at 07:31
  • With callback approach, it works well. So, I think there is no problem at line `const collection = db.collection('transaction')` and `collection.find({ user_id: id})...` – Vu Le Anh Aug 01 '19 at 07:51
  • Try with `console.log(db.collection('transaction'))` - if it's a Promise you have to do `const collection = await db.collection('transaction')` – Andrea Franchini Aug 01 '19 at 08:42
  • it's an object, not a Promise. – Vu Le Anh Aug 01 '19 at 08:53