簡體   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