Promisify导入类(构造函数)与蓝鸟在ES6 + babel [英] Promisify imported class (constructor) with bluebird in ES6 + babel
问题描述
假设我创建或有一个node.js库 lib.js
Suppose I created or have a node.js library lib.js
export class C {
constructor(value, callback) {
callback(false, `Hello ${value}`);
}
task(value, callback) {
callback(false, "returned " + value);
}
}
重要的是类的构造函数需要接受回调,因为它执行数据库连接和文件I / O。如果我现在导入和使用库回调风格,一切都很好(见下面 c1
)。
The important part is that the classes' constructor needs to accept a callback as it does database connections and file I/O. If I now import and use the library callback-style, everything is fine (see c1
below).
我真的想宣传图书馆,我用它来使对象构造更方便(在现实中,它是一大堆课程,方法)。
I would really like to promisify the library where I use it to make object construction more convenient (in reality it's a whole bunch of classes and methods).
但是,我找不到一个方法来新
类中正确的promise安全很好。
However, I can't find a way to new
the class properly in a promise-safe nicely.
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 = ???
我该如何做到最好?更改库签名不是一个好的选择,创建工厂方法也似乎是难看的。
How would I do this best? Changing library signature isn't a good option, creating factory methods also seems to be ugly.
推荐答案
我将从它开始:不要在构造函数中做IO是绑定io和构造在一起的一个坏主意。
I feel strongly about this so I'll start with it: Don't do IO in constructors it's a bad idea to bind io and construction together.
也就是说,如果必须这样做,因为库是不受你的控制,并且可以失去以同步方式构建对象的能力,你可以:
That said, if you must do this because the library is out of your control and are OK with losing the ability to build objects in a sync way, you can:
export class C {
constructor(value, callback) {
callback(false, `Hello ${value}`);
}
task(value, callback) {
callback(false, "returned " + value);
}
}
并且当promisifying时:
And when 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
};
这将允许你使用返回值和promise,promise只会有一个然后
所以你可能想要 Promise.resolve
它得到一个真正的promise而不是一个对象的属性和 a promise。
Which would let you both use the return value and the promise, the promise will only have a then
so you might want to Promise.resolve
it to get a "real" promise rather than an object with properties and a promise.
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导入类(构造函数)与蓝鸟在ES6 + babel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!