I am trying to refactory my nodejs server using promises with Bluebird library, but I am stuck in a simple problem.
After to get the users from my db, I want to list all notification class associated with this user:
Bad Way (working...)
adapter.getUsers(function(users){
users.rows.forEach(function(item){
user = item.username;
adapter.getNotifications(user, function(notificationList){
console.log(notificationList);
})
});
});
Elegant Tentative Way (not working...)
var getNotifications = Promise.promisify(adapter.getNotifications);
adapter.getUsers().then(function(users) {
users.rows.forEach(function(item){
var dbUser = "sigalei/" + item.value.name;
console.log(dbUser);
return getNotifications(dbUser);
});
}).then(function(result){
console.log(result);
console.log("NOTIFICATIONLIST");
});
However when I execute this code I get this error inside my getNotification method:
Unhandled rejection TypeError: Cannot read property 'nano' of undefined at Adapter.getNotifications (/Users/DaniloOliveira/Workspace/sigalei-api/api/tools/couchdb-adapter.js:387:30) at tryCatcher (/Users/DaniloOliveira/Workspace/sigalei-api/node_modules/bluebird/js/main/util.js:26:23)
EDIT
After the user2864740`s precious comments, I noticed that the error is related with some scope problem. So, why after to use promisify method, the method dont getNotifications recognize the "this" env variable?
var Adapter = module.exports = function(config) {
this.nano = require('nano')({
url: url,
request_defaults: config.request_defaults
});
};
Adapter.prototype.getNotifications = function(userDb, done) {
var that = this;
console.log(that);
var userDbInstance = that.nano.use(userDb);
userDbInstance.view('_notificacao', 'lista',
{start_key: "[false]", end_key: "[false,{}]"},
function(err, body) {
if(err){ done(err); }
done(body);
});
};
What about simply
or possibly
?
I'm not sure I understand your problem well, but this should make sure
this
is bound and notundefined
when you doreturn getNotifications(dbUser);
This is just the very common problem of calling "unbound" methods.
You can pass the context as an option to
Promise.promisify
to have it bound:Alternatively, you'd need to
.bind()
the method, or call the newgetNotifications
function on theadapter
(using.call()
). You might also consider usingPromise.promisifyAll(adapater)
and then just callingadapter.getNotificationsAsync(…)
.Notice that this still doesn't work. You cannot simply create promises in a loop - you need to await them explicitly and return a promise from the
then
callback, otherwise just theundefined
value you returned will be passed to the next callback immediately.Instead of
Promise.all(users.rows.map(…))
, in Bluebird you can also usePromise.map(users.rows, …)
.