I understand Promises in JavaScript or atleast I think I do (correct me if Im wrong).
Create a Promise:
var promise = new Promise(function(resolve, reject){
// do something async here
if(itWorked){
resolve();
}else {
reject();
}
});
Use a Promise:
promise.then(function(result){
},function(err){
});
I have an app based on MEAN Stack and some of my mongoose routes are becoming a callback hell. I want move away from callbacks in mongoose routes and handle them using Promises. But I can't seem to figure out how exactly to do that.
For example:
app.get('/users', function(req, res){
User.findOne(_id, function(err, user){
if(err)
console.log(err)
else if(user){
Receipt.findOne(user.bookName, function(err, book){
if(err)
console.log(err)
else if(book){
// again do something here
}
})
}
})
});
In the above example you can see that the code is getting harder to read and maintain. How can I use Promises here to improve my code?
Ok, first are you using mongoose
right?
User
is your mongoose model which responds to methods such as findOne(query)
, findOneAndUpdate(query, update, opts)
etc..
After calling any of these methods, call the method exec()
which returns a Query.
A Query is not exactly a Promise and you'll need to specify which Promises will Mongo use. Here I would recommend to use the native ones so, add this line at your project:
const mongoose = require('mongoose')
mongoose.Promise = Promise
Now, this instruction is returning you a Promise, nice!
User.findOne(q).exec()
You can now create a Promise chain with your logic, for example:
return User
.findOne(_id)
.exec()
.then((user) => {
return Receipt
.findOne({ bookName: user.bookName })
.exec()
})
.then((receipt) => {
// example
return res.status(200).json(receipt)
}))
})
Tip: I'd suggest to create aux methods in order to make the code even more cleaner:
/** @return {Promise} */
function findUser(id) {
return User.findOne(id).exec()
}
/** @return {Promise} */
function findReceipt(bookName) {
return Receipt.findOne({ bookName }).exec()
}
// example
function f(req, res) {
const userId = req.get('id')
return findUser(userId)
.then((user) => findReceipt(user.bookName))
.then((receipt) => res.status(200).json(receipt))
.catch((err) => res.status(500).json(null))
}
// register your handler
app.get('/book', f)