如何确保正确的“这个”与Promise.promisify? [英] How to ensure correct "this" with Promise.promisify?
问题描述
我正在尝试使用与Bluebird库的promises重构我的nodejs服务器,但我遇到了一个简单的问题。
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(正在工作......)
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");
});
然而,当我执行此代码时,我在getNotification方法中出现此错误:
However when I execute this code I get this error inside my getNotification method:
未处理的拒绝TypeError:无法在Adapter.getNotifications上读取未定义
的属性'nano'(/ Users / DaniloOliveira / Workspace / sigalei-api / api / tools / couchdb-adapter.js:387:30)在tryCatcher上的
(/Users/DaniloOliveira/Workspace/sigalei-api/node_modules/bluebird/js/main/util.js:26:23)
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)
编辑
在用户2864740的宝贵评论之后,我注意到了错误与某些范围问题有关。那么,为什么在使用promisify方法之后,方法dont getNotifications会识别thisenv变量?
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);
});
};
推荐答案
这只是非常常见的调用未绑定方法的问题。
您可以将上下文作为选项传递给 Promise.promisify
让它绑定:
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:
var getNotifications = Promise.promisify(adapter.getNotifications, {context: adapter});
或者,你需要 .bind()
方法,或在适配器
上调用新的 getNotifications
函数(使用。呼叫()
)。您也可以考虑使用 Promise.promisifyAll(adapater)
,然后只需调用 adapter.getNotificationsAsync(...)
。
Alternatively, you'd need to .bind()
the method, or call the new getNotifications
function on the adapter
(using .call()
). You might also consider using Promise.promisifyAll(adapater)
and then just calling adapter.getNotificationsAsync(…)
.
请注意,这仍然无效。你不能简单地在循环中创建promises - 你需要显式地等待它们并从然后
回调返回一个promise,否则只是 undefined
您返回的值将立即传递给下一个回调。
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 the undefined
value you returned will be passed to the next callback immediately.
adapter.getUsers().then(function(users) {
return Promise.all(users.rows.map(function(item){
var dbUser = "sigalei/" + item.value.name;
console.log(dbUser);
return getNotifications(dbUser);
}));
}).then(function(results) {
for (var i=0; i<results.length; i++)
console.log("result:", results[i]);
});
而不是 Promise.all(users.rows.map(...))
,在Bluebird中你也可以使用 Promise.map(users.rows,...)
。
Instead of Promise.all(users.rows.map(…))
, in Bluebird you can also use Promise.map(users.rows, …)
.
这篇关于如何确保正确的“这个”与Promise.promisify?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!