[英]What is the difference between net.connect and net.createConnection in node.js?
[英]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()
行。 承諾只能被解決或拒絕一次,因此您不必擔心再次調用您的事件。 承諾一旦滿滿就不會改變它的狀態。
而且,我認為你有幾個問題需要解決:
var connect_args = arguments
可能不起作用,因為arguments
是一種時髦對象的時髦類型。 通常的解決方法是復制它的內容: var connect_args = [].slice.call(arguments);
。
在這一行中, 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
}
事情一個接一個地運行:
- 輸入try塊
- 用參數
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
采用節點樣式的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.