From the docs (Mongoose v5.4.1, latest version):
Mongoose async operations, like .save() and queries, return thenables. This means that you can do things like MyModel.findOne({}).then()
second parapraph from the docs states:
Mongoose queries are not promises. They have a .then() function for co and async/await as a convenience.
What Javascript MDN webpage states:
The then() method returns a Promise.
Does this mean that mongoose has another kind of implementation for async functions where they reserved the then keyword for the result of the async action?
In other words, they act like promises but are not JS promises?
From the documentation:
So unlike an actual promise, if you call
then()
multiple times on the query, you actually execute the query (or update) multiple times.If you want an actual promise, call
exec()
on the query.All promises are thenables, but not all thenables are promises. To make things more complicated, not all promises are
Promise
s (instances created by JavaScript's built-inPromise
constructor).JavaScript promises are an implementation of the Promises/A+ specification, which defines the terms like this:
So Mongoose's queries are not promises, not even by that definition, since their
then
method is not compatible with the Promises/A+ spec. See JohnnyHK's answer for why they aren't compatible with the Promises/A+ spec (they run the query).They only act a bit like promises. They are not promises. Their
then
is not implemented per the spec, it has side effects (running the query). If you want a true promise, see JohnnyHK's answer (e.g., useexec
).In general, if you have a thenable that's at least somewhat promise-like, you can get a proper promise for it by using
Promise.resolve
:Promise.resolve
will provide a truePromise
instance that is slaved to the Mongoose thenable/promise. That would work on a Mongoose query (provided you only do it once;exec
is the better way with Mongoose queries).They are "promise like", which means you can
await
them and call.then()
and.catch()
on them, however they are notinstanceof Promise
.