Hello everyone,
I'm using mongoose version 5.0.3 and node version 9.4.0. According to mongoose documentation model.create should return a promise which, I assume, is resolved as the document created is saved in the DB. However as shown by the code below it seems that the promise is resolved before the document is saved in the DB.
async function test(){
let schema = new mongoose.Schema({a: String});
let model = mongoose.model('test', schema);
await model.remove({}).exec();
await model.create({ a: 'test'},
(err,result)=> {console.log('created');});
await model.findOneAndUpdate(
{ a : 'test' } ,
{ a: 'newValue'}
)
.exec((err, result) => {
console.log('update : '+result);
});
await model.find({a: 'test'},(err,result) => {
console.log(result);
});
}
output in terminal :
update : null
found :
created
findOneAndUpdate do not find any document. In addition to that "created" is appearing at the end in the terminal, hence the callback of the create method is executed as if the await was not waiting for the async task 'create' to be done.
However by adding a promise which is resolved once the callback of create is triggered, as shown below, we obtain the expected result :
async function test(){
let schema = new mongoose.Schema({a: String});
let model = mongoose.model('test', schema);
await model.remove({}).exec();
await new Promise((resolve,reject) => {
model.create({ a: 'test'},
(err,result)=> {
console.log('created');
resolve();
});
});
await model.findOneAndUpdate(
{ a : 'test' } ,
{ a: 'newValue'}
)
.exec((err, result) => {
console.log('update : '+result);
});
await model.find({a: 'newValue'},(err,result) => {
console.log('found : ' +result);
});
}
output in terminal:
created
update : { _id: 5a735fbc1fe826233014d62d, a: 'test', __v: 0 }
found : { _id: 5a735fbc1fe826233014d62d, a: 'newValue', __v: 0 }
Now we have the expected result.
All functions which operate on the DB do return a promise that if resolved indicates that the operation has been done, specifically Query. I assume that was also the case of model.create although it doesnt return a query object strictly speaking. I also wonder what the fulfilled returned promise means as it does not show that the doc was created in the DB. Perhaps I missed the whole point but I find it a bit ambiguous
I believe I remember reading in the 4.x docs that if you pass a callback to model.create it doesn't return a promise.
let x = model.create({ a: 'test' }, () => {})
x.then(console.log(x)) //TypeError: Cannot read property 'then' of undefined
if you pull out the callback:
let x = model.create({ a: 'test' })
x.then(console.log(x)) // Promise { <pending> }
the 5.x source for model.js bears this out calling utils.promiseOrCallback
Yup, @lineus is correct, can I close out this issue @CodeurSauvage ?
@CodeurSauvage @lineus is correct, mongoose 5 does not return a promise if a callback is specified. Your script works if you replace:
await model.create({ a: 'test'},
(err,result)=> {console.log('created');});
With:
await model.create({ a: 'test'}).then(result => console.log('created'));
Most helpful comment
I believe I remember reading in the 4.x docs that if you pass a callback to model.create it doesn't return a promise.
if you pull out the callback:
the 5.x source for model.js bears this out calling utils.promiseOrCallback