我如何正确编写一个模块来与Bluebird的PromisifyAll兼容

比方说,在node.js模块moduleA.js ,我有以下一些节点式asynchronous函数:

 // moduleA.js var init = function (data, callback) { return callback(null, data.params ); }; var delay = function(data, callback) { setTimeout(function(){ callback(null, data); }, 1000*3); } var reverse = function(data, callback) { var j, d = {}; for(j in data) { d[ data[j] ] = j; } callback(null, d); } module.exports = { init: init, delay: delay, reverse: reverse }; 

我在main.js使用moduleA.js ,并且可以单独地成功promisify每个方法,如:

 // main.js var Promise = require('bluebird'), modA = require('./moduleA') ); var data = { "a": "one", "b": "two", "c": "three", "d": "four" }; Promise.promisify(modA.init)(data) .then( Promise.promisify(modA.delay) ) .then( Promise.promisify(modA.reverse) ) .then(function(data){ res.send(data); }).catch(function(e){ next(e); }); 

上面的代码工作得很好,但比所需的更详细。

我的问题是,我将如何修改我的模块,以允许Promise.promisifyAll在整个导出的对象上正常工作? 我想避免模块内部的promisification ,并允许其他人在消费时select性的promisify

我没有成功尝试以下的许多变化:

 // main.js var Promise = require('bluebird'), modA = require('./moduleA') ), modAPromised = Promise.promisifyAll(modA); var data = { "a": "one", "b": "two", "c": "three", "d": "four" }; modAPromised.initAsync(data) .then(modAPromised.delayAsync) .then(modAPromised.reverseAsync) .then(function(data){ res.send(data); }).catch(function(e){ next(e); }); 

当我这样做,我得到和错误,说Cannot call method 'delay' of undefinedPromise.promisifyAll正在按照预期添加所有Async函数:

 // console.log(modAPromised); { init: [Function], delay: [Function], reverse: [Function], initAsync: { [Function] __isPromisified__: true }, delayAsync: { [Function] __isPromisified__: true }, reverseAsync: { [Function] __isPromisified__: true } } 

但是我觉得有些东西是与上下文矛盾的。 看来,内部的delayAsync试图调用this.delay但这是未定义的。

那么,如何修改我的模块以允许Promise.promisifyAll在整个导出的对象上正常工作?

提前致谢。

promisifyAll创build依赖于this方法,因为当你将一个类的原型传递给它时, this是不知道的。

例如:

 Promise.promisifyAll(require("redis")); // In another file var redis = require("redis"); var client1 = redis.createClient(...); var client2 = redis.createClient(...); client1.putAsync(...); client2.putAsync(...); 

"redis"被promisified时,没有什么可以绑定的,而这些方法依赖于特定的client实例。 .putAsync不能直接调用put – 它需要调用putclient1putAsync的上下文中,具体取决于如何putAsync

有人提出了一个解决scheme,但他从来没有回应: https : //github.com/petkaantonov/bluebird/issues/470 。


你的模块可以实现为使用nodeify的双重API,这样消费者甚至不需要promisification:

 var init = function (data, callback) { return Promise.resolve(data.params).nodeify(callback); }; var delay = function(data, callback) { return Promise.delay(data, 1000 * 3).nodeify(callback); } var reverse = function(data, callback) { var j, d = {}; for(j in data) { d[ data[j] ] = j; } return Promise.resolve(d).nodeify(callback); } 

你的问题less于moduleA.js ,在main.js使用main.js

如果您在.then .then()语句中显式调用promisified函数,则模块将正常工作:

 // main.js var Promise = require('bluebird'), modA = require('./moduleA'), modAPromised = Promise.promisifyAll(modA); var data = { "a": "one", "b": "two", "c": "three", "d": "four" }; modAPromised.initAsync(data) .then(function(data) { return modAPromised.delayAsync(data); }) .then(function(data) { return modAPromised.reverseAsync(data); }) .then(function(data){ res.send(data); }).catch(function(e){ next(e); }); 

至于这是为什么 ,我真的不知道。 我有一个强烈的怀疑promisifyAll做一些背景约束, promise不会做。 这可以解释为什么用干净的函数包装你的方法可以解决这个问题。

我相信Bluebird的维护者会知道更多,如果你想得到具体的实施。