0

As part of another question I am trying to promisify a mongo/mongoose find query. I found little help via the search bar. The query is below, I am running this query as part of a controller in express. Setup is route -> userController.monitor which needs to contain the query

In getting help for the other question I was asked to promisify find so that you can use await for it (like const incidents = Incident.find({fooID}).exec(); though SO search and my attempts at promisifying it myself have failed.

Query:

Incident.find({fooID})
.exec((err, incidents) => {
// do something
})

Note a findOne will not work in this case because multiple documents will be returned almost all the time

Edit

Incident.find({ monitorID, createdAt: {$gte: sevenAgo} })

joshk132
  • 1,011
  • 12
  • 37
  • Doesn't mongoose already return promises if no callback is passed, so `const incidents = Incident.find({fooID}).exec();` would literally work? – Bergi May 28 '20 at 21:45
  • Otherwise, did you not find [How do I convert an existing callback API to promises?](https://stackoverflow.com/q/22519784/1048572) – Bergi May 28 '20 at 21:45
  • Oh, sorry, I again forgot to spell the `await` where I meant to. Should be `const incidents = await Incident.find({fooID}).exec();` of course. – Bergi May 28 '20 at 21:51
  • @Bergi This question was posted in response to your request in my other question. How you are suggesting to do it is something I already had before hand. – joshk132 May 28 '20 at 21:53

1 Answers1

0

You can create a promisified version of your find function using the promisify function in the util module of node.js

const { promisify } = require('util')

const promisifiedIncidentFindExec = payload => {
  const query = Incident.find(payload)
  return promisify(query.exec).call(query)
}

const incidents = await promisifiedIncidentFindExec({
  monitorID: 'monitorID',
  createdAt: { $gte: 'sevenAgo' },
})
// do something
richytong
  • 2,387
  • 1
  • 10
  • 21
  • I see you are using `fooID` in a few places, I see the initial one and take that as an input? Second is search param, and third is passing in the search param? Also getting this when trying your answer `UnhandledPromiseRejectionWarning: CastError: Cast to string failed for value "{ fooID: '5eaa08fb4ed2aaa044efa043' }" at path "fooID" for model "Incident"` However when I `console.log(typeof fooID)` I get back `string` so should be no issues with it showing as an object/not a string – joshk132 May 28 '20 at 20:59
  • hmm, maybe try `const query = Incident.find(fooID)`? So just pass the string in there – richytong May 28 '20 at 21:40
  • My actual query has a bit more than just `fooID` so I added the full query param to the OP to show, not much difference just one thing added – joshk132 May 28 '20 at 21:44
  • 1
    You should rather do `return promisify(query.exec).call(query)` to make use of `promisify`'s caching – Bergi May 28 '20 at 21:47
  • the `.call` inherently binds the context – richytong May 28 '20 at 21:49
  • 1
    Same as `.bind(query)()`, but without unnecessarily creating yet another function :-) – Bergi May 28 '20 at 21:52