在ES6 + babel中用蓝鸟Promisify导入类(构造函数)

假设我创build了或有一个node.js库lib.js

 export class C { constructor(value, callback) { callback(false, `Hello ${value}`); } task(value, callback) { callback(false, "returned " + value); } } 

重要的部分是类的构造函数需要接受一个callback,因为它做的是数据库连接和文件I / O。 如果我现在导入并使用库callback样式,则一切正常(请参阅下面的c1 )。

我真的很想在图书馆中使用它来使对象构造更加方便(实际上它是一大堆类和方法)。

但是,我无法在保证安全的前提下正确地findnew的课程。

 import Promise from 'bluebird'; import * as lib from './lib'; Promise.promisifyAll(lib); // old style -- works as expected const c1 = new lib.C("c1", (e, v) => { console.log(c1, e, v); }); // assuming c1 got initialized, .task() also works c1.task("t1", console.log); c1.taskAsync("t2").then(() => console.log("also works")); // But how to do this properly with promises? const c2 = new lib.C("c2"); c2.then(console.log); // clearly doesn't work, lack of callback const c3 = new lib.CAsync("c3"); c3.then(console.log); // "cannot read property apply of undefined" const c4 = ??? 

我怎样才能做到最好? 更改库签名不是一个好的select,创build工厂方法也似乎是丑陋的。

我对此深有感触,所以我将从此开始:不要在构造函数中做IO,将io和构造绑定在一起是一个坏主意。

也就是说,如果你必须这样做,因为库不在你的控制之下,并且没有能力以同步的方式build立对象,你可以:

 export class C { constructor(value, callback) { callback(false, `Hello ${value}`); } task(value, callback) { callback(false, "returned " + value); } } 

当promisifying:

 import Promise from 'bluebird'; import * as lib from './lib'; Promise.promisifyAll(lib); var old = lib.C; // reference the constructor lib.C = function(value){ // override it o; // object we'll later return, populate in promise constructor var p = new Promise(function(resolve, reject){ // the promise constructor is always sync, so the following works o = new old(value, function(err, data) { if(err) return reject(err); resolve(data); }); }); // THIS IS THE IMPORTANT PART o.then = p.then.bind(p); // make the object a thenable, return o }; 

哪个可以让你使用返回值和承诺,承诺只会有一个then所以你可能想要Promise.resolve它来获得一个“真正的”承诺,而不是一个具有属性承诺的对象。

 var o = new lib.C(); // get object o.then(function(data){ // access data }); 

这可以提取到一个模式:

  function promisifyConstructor(cons){ return function(...args) => { // new constructor function let o; let p = new Promise((resolve, reject) => { // delegate arguments o = new cons(...args, (err, data) => err ? reject(err) : resolve(data)); }); o.then = p.then.bind(p); return o; } } 

你不能直接promisify构造函数(我知道),但你可以平凡的解决方法与工厂方法:

 function createC(value) { return new Promise(function (res, rej) { var c = new C(value, function (err, val) { if (err) { rej(err); } else { res(val); // or res(c) if you prefer } }); }); } 

我不认为有一个更漂亮的方法,build造良好的工厂不应该太难看。 你可以概括工厂采取任何forms的构造函数,但是你接近完整的DI,这可能是值得find一个承诺友好的DI库。