Promises
Built-in Promises
Mongoose async operations, like .save()
and queries, return thenables.
This means that you can do things like MyModel.findOne({}).then()
and
await MyModel.findOne({}).exec()
if you're using
async/await.
You can find the return type of specific operations in the api docs You can also read more about promises in Mongoose.
const gnr = new Band({
name: "Guns N' Roses",
members: ['Axl', 'Slash']
});
const promise = gnr.save();
assert.ok(promise instanceof Promise);
promise.then(function (doc) {
assert.equal(doc.name, "Guns N' Roses");
});
Queries are not promises
Mongoose queries are not promises. They have a .then()
function for co and async/await as
a convenience. If you need
a fully-fledged promise, use the .exec()
function.
const query = Band.findOne({name: "Guns N' Roses"});
assert.ok(!(query instanceof Promise));
// A query is not a fully-fledged promise, but it does have a `.then()`.
query.then(function (doc) {
// use doc
});
// `.exec()` gives you a fully-fledged promise
const promise = query.exec();
assert.ok(promise instanceof Promise);
promise.then(function (doc) {
// use doc
});
Queries are thenable
Although queries are not promises, queries are thenables.
That means they have a .then()
function, so you can use queries as promises with either
promise chaining or async await
Band.findOne({name: "Guns N' Roses"}).then(function(doc) {
// use doc
});
Should You Use exec()
With await
?
There are two alternatives for using await
with queries:
await Band.findOne();
await Band.findOne().exec();
As far as functionality is concerned, these two are equivalent.
However, we recommend using .exec()
because that gives you
better stack traces.
[require:Should You Use `exec()` With `await`]
Plugging in your own Promises Library
If you're an advanced user, you may want to plug in your own promise
library like bluebird. Just set
mongoose.Promise
to your favorite
ES6-style promise constructor and mongoose will use it.
const query = Band.findOne({name: "Guns N' Roses"});
// Use bluebird
mongoose.Promise = require('bluebird');
const bluebirdPromise = query.exec();
assert.equal(bluebirdPromise.constructor, require('bluebird'));
// Use q. Note that you **must** use `require('q').Promise`.
mongoose.Promise = require('q').Promise;
const qPromise = query.exec();
assert.ok(qPromise instanceof require('q').makePromise);
Want to learn how to check whether your favorite npm modules work with
async/await without cobbling together contradictory answers from Google
and Stack Overflow? Chapter 4 of Mastering Async/Await explains the
basic principles for determining whether frameworks like React and
Mongoose support async/await.
Get your copy!