In my project I use async
for asynchronous queries to the database and I have this piece of code:
async.auto({
one: function(callback){
getFriendsIds(userId, callback)
},
two: ['one', function(callback, results){
getFriendsDetails(results.one, callback);
}],
final: ['one', 'two', function(callback, results) {
res.status(200).send(results.two);
return;
}],
}, function(err) {
if (err) {
sendError(res, err);
return;
}
});
The method returning friends' ids looks like this:
function getFriendsIds(userId, callback) {
var query = User.findOne({_id: userId});
query.exec(function(err, user) {
if(err) {
callback(err);
return;
}
return callback(null, user.friendsIds);
});
}
It worked perfectly. The function returned friends' ids and I used them in the "two" block of async call.
After upgrading mongoose
from 4.3.7
to 4.7.8
it stopped working. I started getting Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead
warning and ids were not returned in the callback anymore.
So I added bluebird
package to the project and plugged it in to the mongoose
. Now the warning is gone, but ids are still not returned in the callback.
I also upgraded async
to the newest version, but it didn't help either.
Is there anything more I should do in order to make this work?
The idea of using promises is to not use callbacks, and you're still using callbacks in your code.
Assuming you require bluebird like
mongoose.Promise = require('bluebird');
your function should now instead look like this:
function getFriendsIds(userId) {
//This will now be a bluebird promise
//that you can return
return User.findOne({_id: userId}).exec()
.then(function(user){
//return the friendIds (this is wrapped in a promise and resolved)
return user.friendsIds;
});
}
The returning value of the function will be an array of the user.friendsIds
. Taking advantage of the chaining possibilities of promises, you can write a function that fetches the details of each friend, and return that as an array of friendDetails
.
function getFriendsDetails(friendIds) {
//For each friendId in friendIds, get the details from another function
//(Promise = require("bluebird") as well)
return Promise.map(friendIds, function(friendId) {
//You'll have to define the getDetailsOfFriend function
return getDetailsOfFriend(friendId);
});
}
and simply call it like
getFriendsIds(123)
.then(getFriendsDetails) //the resolved value from previous function will be passed as argument
.then(function(friendDetails) {
//friendDetails is an array of the details of each friend of the user with id 123
})
.catch(function(error){
//Handle errors
});
If you want to write less code, you can let bluebird promisify the mongoose functions like this
Promise.promisify(User.findOne)(123)
.then(function(user){
return user.friendsIds;
})
.then(getFriendsDetails)
.then(function(friendDetails) {
//Return or do something with the details
})
.catch(function(error){
//Handle error
});