Promises in Mongoose
Mongoose has built-in support for promises. In Mongoose 5, async operations like .save()
and
.find().exec()
return a promise unless you pass a callback.
const Model = mongoose.model('Test', Schema({
name: String
}));
const doc = new Model({ name: 'Neo' });
const promise = doc.save();
promise instanceof Promise; // true
const res = doc.save(function callback(err) {
/*...*/
});
res; // undefined
The mongoose.Promise
Property
The Mongoose singleton has a Promise
property that you can use to set the promise library Mongoose uses. For example, you can make Mongoose use the popular Bluebird promise library:
const Bluebird = require('bluebird');
// Make Mongoose use Bluebird instead of built-in promises.
mongoose.Promise = Bluebird;
const doc = new Model({ name: 'Neo' });
const promise = doc.save();
promise instanceof Promise; // false
promise instanceof Bluebird; // true
If you haven't upgraded to Mongoose 5 yet, you might see the below deprecation warning in Mongoose 4.x:
WARNING: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead
To resolve that deprecation warning, you would add the below code:
mongoose.Promise = global.Promise;
That's because one of the breaking changes in Mongoose 5 was switching to using Node.js' native promises. Mongoose 4 was released before ES6, so it had its own promise implementation that was slightly different from native JavaScript promises.
If you see mongoose.Promise = global.Promise
in code that uses Mongoose 5,
please delete it. Mongoose 5 uses native promises by default, so that code
does nothing in Mongoose 5.
Queries are not Promises
While save()
returns a promise, functions like Mongoose's find()
return a Mongoose Query
.
const query = Model.find();
query instanceof Promise; // false
query instanceof mongoose.Query; // true
Mongoose queries are thenables.
In other words, queries have a then()
function that behaves similarly to the Promise then()
function. So you can use queries with promise chaining and async/await.
// Using queries with promise chaining
Model.findOne({ name: 'Mr. Anderson' }).
then(doc => Model.updateOne({ _id: doc._id }, { name: 'Neo' })).
then(() => Model.findOne({ name: 'Neo' })).
then(doc => console.log(doc.name)); // 'Neo'
// Using queries with async/await
const doc = await Model.findOne({ name: 'Neo' });
console.log(doc.name); // 'Neo'