Javascript 如何Promisify node.js net.connect(与bluebird一起)?
我想要node.js函数的Promise版本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
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
}
事情一个接一个地发展:
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没有问题=