2015-09-10 16 views
8

Próbuję refactor mój serwer nodejs przy użyciu obietnic z biblioteki Bluebird, ale utknąłem w prosty problem.Jak zapewnić prawidłowe "to" za pomocą Promise.promisify?

Po dostać użytkowników z mojego db, chcę wymienić całą klasę powiadamiania związanego z tym użytkownikiem:

zły sposób (praca ...)

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

Elegancki Wstępna Way (nie działa ...)

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

jednak kiedy wykonanie tego kodu otrzymuję ten błąd w moim sposobie 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

Po user2864740`s cennych uwag, zauważyłem, że błąd jest związany z pewnym problemem zakres. Dlaczego więc po użyciu metody promisify, metoda dont getNotifications rozpoznaje "tę" zmienną 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

Hej, błąd jest generowany wewnątrz metody getNotifications, która jest "promisify". –

+0

@ user2864740 Ponownie, zredagowałem pytanie, myślę, że problem jest związany ze zmiennymi zasięgu ... –

+0

Wypróbuj '.call()' go z 'adapterem' w' this'. – Amit

Odpowiedz

6

To jest po prostu bardzo często problem of calling "unbound" methods.
można przekazać kontekst jako opcja do Promise.promisify mieć ona związana:

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

Ewentualnie trzeba by .bind() metodę, lub wywołać nową getNotifications funkcję na adapter (używając .call()). Możesz również rozważyć użycie Promise.promisifyAll(adapater), a następnie wywołanie adapter.getNotificationsAsync(…).

Należy zauważyć, że to nadal nie działa. Nie możesz po prostu tworzyć obietnic w pętli - musisz ich wyraźnie oczekiwać i zwrócić obietnicę z połączenia zwrotnego then, w przeciwnym razie tylko zwrócona wartość undefined zostanie natychmiast przekazana do następnego wywołania zwrotnego.

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

Zamiast Promise.all(users.rows.map(…)), w Bluebird można również użyć Promise.map(users.rows, …).

+0

Masz rację, dziękuję za szczegółowe wyjaśnienie tego pytania i metody "niezwiązane". –

+1

W Bluebird 3.4.6 kontekst jest związany w następujący sposób: 'Promise.promisify (adapter.getNotifications, {context: adapter}); ' –

+0

@CryptixMaster Dzięki, zaktualizowany do 3.0 dokumentów i kodu :-) – Bergi

1

co po prostu

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

lub ewentualnie

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

?

Nie jestem pewien, czy rozumiem problemu dobrze, ale to powinno upewnić this jest związany i nie undefined kiedy robisz return getNotifications(dbUser);

Powiązane problemy