Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何Promisify node.js net.connect(与bluebird一起)?_Javascript_Node.js_Promise_Bluebird - Fatal编程技术网

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

Javascript 如何Promisify node.js net.connect(与bluebird一起)?,javascript,node.js,promise,bluebird,Javascript,Node.js,Promise,Bluebird,我想要node.js函数的Promise版本net.connect。如果连接成功,则应使用套接字解决承诺问题;如果存在连接错误,则应错误地拒绝承诺问题;如果取消承诺,则最好也可以取消承诺,因为取消承诺将停止连接尝试 我自己做了一次快速尝试,但尚未实施取消: function connectAsync() { var connect_args = arguments; return new Promise(function (resolve, reject) { v

我想要node.js函数的Promise版本
net.connect
。如果连接成功,则应使用套接字解决承诺问题;如果存在连接错误,则应错误地拒绝承诺问题;如果取消承诺,则最好也可以取消承诺,因为取消承诺将停止连接尝试

我自己做了一次快速尝试,但尚未实施取消:

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()
行。承诺只能被解决或拒绝一次,这样你就不必担心你的活动会被再次调用。承诺一旦兑现,就不会改变它的状态

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

  • var connect\u args=arguments
    可能不起作用,因为
    arguments
    是一种时髦的时态对象。通常的解决方法是复制它的内容:
    var connect_args=[].slice.call(参数)

  • 在这一行中,
    net.connect.apply(this,connect_args)
    ,我不认为
    这个
    是正确的值,因为此时您在promise回调中(在这种特殊情况下,这可能无关紧要)。使用
    net.connect.apply(net,connect_args)可能在技术上更为正确
    这将更直接地模拟调用
    net.connect(args)

  • 至于使用承诺是否明智,你在评论中似乎对此有一些看法

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


    注意:如果不删除
    removeListener()
    代码行,可能会出现错误,因为您正在为
    'connect'
    设置事件,但正在执行
    removeListener('connection
    )。另外,我不知道为什么要将函数传递给
    removeListener()
    ,因为它与您在创建事件处理程序时使用的函数引用不同。

    如果您直接查看它,那么所有这些都是非常复杂的抽象

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

    try{
        var value = foo(bar);
        log(value);
    } catch(e){
        // handle error
    }
    
    事情一个接一个地发展:

  • 输入try块
  • 使用参数
    bar运行
    foo
  • 记录值,除非出现错误
  • 如果有错误,请处理它
  • 这就像一条长长的单链操作。承诺就是这样的:

     fooAsync(bar).
     then(log).
     catch(function(){
          // handle error
     });
    
    承诺是锁链。您可以创建几个这样的链,这与表示执行一系列操作的其他并发形式(如线程)类似。它看起来如下所示:

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

                       --Error---->// might join up
    
    另一方面-事件发射器无法保证其触发的事件的名称或类型,节点EventEmitter有一些很酷的功能(如堆栈跟踪和
    错误
    事件),但有一个比承诺更弱的约定-不同的事件发射器触发不同的事件,事件发射器可以执行以下操作:

     fooAsync(bar).
     then(log).
     catch(function(){
          // handle error
     });
    
    它不是一个单一的链-因此,尽管对此进行了多次尝试和讨论-不存在表示事件发送者承诺的通用方法-它们只是在事件处理和事件名称上有太大的不同

    另一方面-
    pg.connect
    接受节点样式的err回调。因此,很容易做出承诺,这些承诺都有很好的规定,并遵守合同


    您所拥有的很好,您可以将其推广到具有两个事件的事件发射器。请记住,您只编写过一次这种样板文件,然后在代码中使用它:)

    我提出的解决方案与您得到的几乎相同:

    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)
    
    我对此提出了一个问题(要求提供文档),但被重定向到您的问题


    我得出的结论是,目前承诺和事件发送者的交集是丑陋的,我不得不接受它。我没有遇到比我们自己发明的更好的建议,所以如果你这样做了,请分享。

    我不建议为此使用承诺。同意@BenjaminGruenbaum,你可以在这里使用事件处理,为什么你需要承诺?只需编写connect,并在promise中捕获事件。我想编写
    。然后(connect())。然后(doThing())。然后(close())
    样式序列。这似乎是数据库访问的标准实践,其中推荐了
    DB.connect
    ——甚至在bluebird示例中也显示了这一点。为什么
    net.connect
    如此不同?可能是我错了,但是所有这些.then()方法都会同时调用。如果您仍然被卡住,我将在下周发布一个答案,以及为什么Bluebird不支持和不支持自动筛选促销活动发射器。感谢您的几点更正!然而,如果我不调用removeListener,这是否意味着只要套接字打开,承诺就会留在内存中,并且不能被垃圾收集?@nakabible——垃圾收集的好观点——这可能是真的。在您的代码中添加一条注释,说明为什么要删除事件侦听器是明智的,因为像我这样的人可以很容易地在以后出现,并且认为这些行可以删除,因为承诺一旦完成就不可变,因此它们不受对
    reject()
    resolve()的多次调用的影响
    var connect\u args没有问题=