繁体   English   中英

如何Promisify node.js net.connect(与bluebird)?

[英]How to Promisify node.js net.connect (with bluebird)?

我想要一个node.js函数net.connect的Promise版本。 如果连接成功,则应使用套接字解析Promise,如果存在连接错误则拒绝错误,并且最好也应该取消,其中取消将停止连接尝试。

我自己做了一个快速尝试,但还没有实现取消:

function connectAsync() {
    var connect_args = arguments;
    return new Promise(function (resolve, reject) {
        var socket = net.connect.apply(this, connect_args);
        socket.once('connect', function () {
            socket.removeListener('error', reject);
            resolve(socket);
        });
        socket.once('error', function (err) {
            socket.removeListener('connection', resolve);
            reject(err);
        });
    });
}

然而,对于这么简单的事情来说,这似乎非常复杂。 有没有更好的办法? 有人已经这样做了吗?

您可以删除两个removeListener()行。 承诺只能被解决或拒绝一次,因此您不必担心再次调用您的事件。 承诺一旦满满就不会改变它的状态。

而且,我认为你有几个问题需要解决:

  1. var connect_args = arguments可能不起作用,因为arguments是一种时髦对象的时髦类型。 通常的解决方法是复制它的内容: var connect_args = [].slice.call(arguments);

  2. 在这一行中, net.connect.apply(this, connect_args); ,我不认为this将是正确的价值,因为你在那个点内的承诺回调(也许在这个特殊情况下无关紧要)。 使用net.connect.apply(net, connect_args);可能在技术上更正确net.connect.apply(net, connect_args); 这将更直接地模拟调用net.connect(args)

至于使用承诺的智慧,看起来你在评论中对此事有几点看法。

除了删除removeListener()代码行之外,我认为没有太多方法可以简化它。 您正在创建一个响应两种不同自定义条件的承诺,因此您必须编写代码来检测这两个条件。 没办法解决这个问题。

PS如果你没有删除removeListener()代码行,你可能会出现错误,因为你正在为'connect'设置一个事件,但是要做一个removeListener('connection )。 另外,我不知道你为什么要将函数传递给removeListener()因为它与你在建立事件处理程序时使用的函数引用不同。

总而言之,如果你直接看它 - EventEmitters ings是一个非常复杂的抽象。

Promise代表排序操作 - 将它们视为赋值运算符或分号。 常规同步编程中的代码类似于:

try{
    var value = foo(bar);
    log(value);
} catch(e){
    // handle error
}

事情一个接一个地运行:

  1. 输入try块
  2. 用参数bar运行foo
  3. 除非出现错误,否则记录该值
  4. 如果有错误,请处理它。

这就像一条长长的单一操作 承诺是这样的:

 fooAsync(bar).
 then(log).
 catch(function(){
      // handle error
 });

承诺是一个链条。 您可以创建多个此类链,这类似于其他形式的并发(如线程),表示执行一系列操作。 它看起来像下面这样:

-------------------------------- + - 成功--------------- --->

  --Error---->// might join up 

另一方面 - 事件发射器无法保证它触发的事件的名称或类型,节点EventEmitter有一些很酷的功能(如堆栈跟踪和error事件)但是有一个比承诺要弱得多的约定 - 不同的事件发射器触发不同的事件,事件发射器可以做这样的事情:

 ----Foo fired-+-Handler 1 ---- Bar fired-+ ---- Baz Fired-+-Handler 1 --Handler 2 --Handler 2 

它不是一个单一的链 - 所以虽然已经有过几次尝试和讨论 - 没有通用的方法来表示来自事件发射器的承诺 - 它们在事件处理和事件名称方面完全不同。

另一方面 - pg.connect采用节点样式的err-callback。 因此很容易实现,这些都是非常明确的,并且遵守合同。

你有什么是好的,你可以将它推广到一个有两个事件的事件发射器。 记住你曾经写过这种样板文件,然后在你的代码中使用它:)

我提出的解决方案与你几乎相同的解决方案相符:

p = new Promise((resolve, reject) ->
    listener = (data) ->
        try
            check_data_format(data)
        catch err
            return reject(err)
        if is_right_data(data)
            return resolve()
    ee.on("stdout", listener)
)
return p

偶尔当事情变得更加不愉快时:

reject_f = null
resolve_f = null
p = new Promise((resolve, reject) ->
    reject_f = reject
    resolve_f = resolve
)
listener = (data) ->
    try
        check_data_format(data)
    catch err
        return reject(err)
    if is_right_data(data)
        return resolve()
ee.on("stdout", listener)

我在这里提出了一个关于此问题(要求提供文件)的问题但是被重定向到您的问题。

我得出结论,当前的承诺和事件发射器的交集只是丑陋而且我必须忍受它。 我没有遇到任何比我们独立发明的更好的建议,所以如果你这样做,请分享。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM