2015-09-10 3 views
8

Я пытаюсь refactory мой nodejs сервер, используя обещания с библиотекой Bluebird, но я застрял в простой проблеме.Как обеспечить правильное «это» с помощью Promise.promisify?

После получить пользователь из моей БД, я хочу, чтобы перечислить все класс уведомления, связанный с этим пользователем:

Bad Way (работой ...)

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

Элегантные Ориентировочный Way (не работает ...)

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:

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 После user2864740`s драгоценных комментариев, я заметил, что ошибка связана с какой-либо проблемами области видимости. Итак, почему после использования метода promisify метод dont getNotifications распознает «эту» переменную env?

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

}; 
+0

Эй, ошибка генерируется внутри метода getNotifications, который «promisify». –

+0

@ user2864740 Опять же, я отредактировал вопрос, я думаю, что проблема связана с переменными сферы ... –

+0

Попробуйте '.call()' вводить его с помощью 'adapter'as' this'. – Amit

ответ

6

Это только очень общий problem of calling "unbound" methods.
Вы можете передать контекст в качестве опции Promise.promisify, чтобы он связан:

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

В качестве альтернативы, вы должны были бы .bind() метод, или вызвать новую getNotifications функцию на adapter (с помощью .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.all(users.rows.map(…)) в Bluebird вы также можете использовать Promise.map(users.rows, …).

+0

Вы правы, спасибо за подробное объяснение этого вопроса и «несвязанные» методы. –

+1

В контексте Bluebird 3.4.6 выполняется следующее: 'Promise.promisify (адаптер.getNotifications, {context: adapter}); ' –

+0

@CryptixMaster Спасибо, обновлено до 3.0 документов и кода :-) – Bergi

1

насчет просто

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

или, возможно,

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

?

Я не уверен, я понимаю вашу проблему хорошо, но это должно убедиться, что this связан и не undefined, когда вы делаете return getNotifications(dbUser);

Смежные вопросы