Promisify导入类(构造函数)与蓝鸟在ES6 + babel [英] Promisify imported class (constructor) with bluebird in ES6 + babel

查看:133
本文介绍了Promisify导入类(构造函数)与蓝鸟在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆