如何承诺node.js net.connect(与bluebird)
How to Promisify node.js net.connect (with bluebird)?
我想要node.js函数net.connect
的Promise版本。如果连接成功,则应使用套接字解决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);
});
});
}
然而,对于这样一件简单的事情来说,这似乎非常复杂。有更好的方法吗?有人已经这么做了吗?
如果你直接看的话,总而言之——EventEmitters是一个非常复杂的抽象。
Promise表示排序操作——可以将其视为赋值运算符或分号。常规同步编程中的代码看起来像:
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有一些很酷的功能(如堆栈跟踪和error
事件),但有一个比承诺弱得多的约定-不同的事件发射器发射不同的事件,事件发射器可以做这样的事情:
----Foo fired-+-Handler 1 ---- Bar fired-+ ---- Baz Fired-+-Handler 1 --Handler 2 --Handler 2
它不是一个单一的链条,因此,尽管已经对此进行了几次尝试和讨论,但不存在表示事件发射器承诺的通用方法,它们在事件处理和事件名称方面差异太大。
另一方面,pg.connect
采用节点式的错误回调。因此,承诺很容易,这些都是非常明确的,并遵守合同。
您所拥有的是好的,并且您可以将其推广为具有两个事件的事件发射器。记住,你只写过一次这种样板,然后在你的代码中使用它:)
您可以删除两个removeListener()
行。承诺只能被解决或拒绝一次,这样你就不必担心你的活动再次被调用。承诺一旦兑现就不会改变它的状态。
而且,我认为你有几个问题需要解决:
-
var connect_args = arguments
可能不起作用,因为arguments
是一种时髦类型的时间对象。通常的工作是复制它的内容:var connect_args = [].slice.call(arguments);
。 -
在这一行中,
net.connect.apply(this, connect_args);
,我认为this
不会是正确的值,因为此时您处于promise回调中(在这种特殊情况下可能无关紧要)。使用net.connect.apply(net, connect_args);
可能在技术上更正确,它将更直接地模拟调用net.connect(args)
。
至于使用承诺是否明智,你在评论中似乎对此事有一些看法。
除了删除removeListener()
行代码之外,我认为没有太多方法可以简化这一点。您正在创建一个承诺来响应两个不同的自定义条件,因此您必须编写代码来检测这两个条件。没办法。
附言:如果您不删除removeListener()
行代码,您可能会出现错误,因为您正在为'connect'
设置事件,但正在执行removeListener('connection
)。此外,我不知道为什么要将函数传递给removeListener()
,因为它与建立事件处理程序时使用的函数引用不同。
我提出的解决方案与您得到的解决方案几乎相同:
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)
我在这里提出了一个问题(要求提供文件),但被重定向到了你的问题。
我得出的结论是,目前承诺和事件发射器的交叉点非常丑陋,我必须接受它。我没有遇到比我们独立发明的更好的建议,所以如果你有,请分享。
- 借助asp.net验证或java脚本对多个文本进行验证
- java.net和javascript之间正则表达式的差异
- 将Javascript数组发送到控制器ASP.NET MVC
- ASP.NET通过单击JavaScript按钮触发c#事件
- 将数据从javascript文件导入VB.Net页面
- 文本框不是从Javascript/Asp.net中的对话框中打印出来的
- 为什么grunt contrib connect的中间件选项的第三个参数是未定义的
- 从javascript调用asp.net codebehind函数
- Grunt-connect在根目录之外提供静态文件
- jQuery Error adadvisor.net
- 使用javascript的Asp.net内容占位符
- 获取ASP.NET Ajax Timer状态
- ASP.NET网络摄像头显示
- 如何在只能有一个asp.net表单的主页上从asp.net页面中的javascript中获取值
- 如何将乳胶配方奶粉图像保存到Asp.net中的文件夹中
- mongoose.connect undefined不是一个函数
- What does connect.facebook.net/en_US/all.js do
- 浏览器中的 Node's net.connect()
- 如何承诺node.js net.connect(与bluebird)
- connect.facebook.net是获得JS SDK的唯一来源吗?