如何确保正确的“this”;Promise.promisify

How to ensure correct "this" with Promise.promisify?

本文关键字:this promisify Promise 何确保 确保      更新时间:2023-09-26

我正在尝试使用承诺与蓝鸟库重构我的nodejs服务器,但我被困在一个简单的问题。

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

Bad Way (working…)

adapter.getUsers(function(users){
    users.rows.forEach(function(item){
        user = item.username;
        adapter.getNotifications(user, function(notificationList){
            console.log(notificationList);
        })
    });
});

优雅的暂定方式(不工作…)

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方法中得到这个错误:

未处理的拒绝TypeError: Cannot read property 'nano' of undefined在适配器。getNotifications(/用户/DaniloOliveira/Workspace/sigalei-api/api/工具/couchdb-adapter.js: 387:30)/Users/DaniloOliveira/Workspace/sigalei-api/node_modules/bluebird/js/main/util.js:26:23)

编辑

在user2864740的宝贵评论之后,我注意到这个错误与一些范围问题有关。那么,为什么使用承诺方法后,方法不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);
    });
};

这是调用"未绑定"方法时最常见的问题。
您可以将上下文作为选项传递给Promise.promisify,使其绑定:

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

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

注意,这仍然不起作用。你不能简单地在循环中创建承诺——你需要显式地等待它们,并从then回调中返回一个承诺,否则你返回的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]);
});

在蓝鸟中,你也可以使用Promise.map(users.rows, …)代替Promise.all(users.rows.map(…))

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

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

?

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