【问题标题】:How to ensure correct "this" with Promise.promisify?如何使用 Promise.promisify 确保正确的“this”?
【发布时间】:2015-12-07 05:08:38
【问题描述】:

我正在尝试使用带有 Bluebird 库的 Promise 重构我的 nodejs 服务器,但我遇到了一个简单的问题。

从我的数据库中获取用户后,我想列出与该用户关联的所有通知类:

不好的方式(工作......)

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 方法中出现此错误:

未处理的拒绝类型错误:无法读取未定义的属性“纳米” 在 Adapter.getNotifications (/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)

编辑

在user2864740宝贵的cmets之后,我注意到这个错误与一些范围问题有关。那么,为什么在使用 promisify 方法后,getNotifications 方法不识别“this”环境变量?

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);
    });

};

【问题讨论】:

  • 嘿,错误是在“promisify”的getNotifications方法内部产生的。
  • @user2864740 再次,我编辑了问题,我认为问题与范围变量有关......
  • 尝试使用.call()ing 与adapter 作为this

标签: javascript promise bluebird


【解决方案1】:

这只是很常见的problem of calling "unbound" methods
您可以将上下文作为选项传递给Promise.promisify 以对其进行绑定:

var getNotifications = Promise.promisify(adapter.getNotifications, {context: adapter});

或者,您需要.bind() 方法,或在adapter 上调用新的getNotifications 函数(使用.call())。您也可以考虑使用Promise.promisifyAll(adapater),然后直接调用adapter.getNotificationsAsync(…)

请注意,这仍然不起作用。您不能简单地在循环中创建 Promise - 您需要显式地等待它们并从 then 回调中返回一个 Promise,否则只有您返回的 undefined 值将立即传递给下一个回调。

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]);
});

在 Bluebird 中,您还可以使用 Promise.map(users.rows, …),而不是 Promise.all(users.rows.map(…))

【讨论】:

  • 你是对的,感谢你对这个问题和“未绑定”方法的详细解释。
  • 在 Bluebird 3.4.6 中,上下文绑定如下:Promise.promisify(adapter.getNotifications, {context: adapter});
【解决方案2】:

那么简单

var getNotifications = Promise.promisify(adapter.getNotifications.bind(adapter));

或者可能

var getNotifications = Promise.promisify(function () {
    return adapter.getNotifications.apply(adapter, arguments);
});

?

我不确定我是否理解你的问题,但这应该确保this 是绑定的,而不是undefined 当你这样做时return getNotifications(dbUser);

【讨论】:

    猜你喜欢
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多