2017-02-24 61 views
-1

我正在爲服務器開發一個簡單的TCP客戶端,並且因爲異步/等待功能而使用最新的節點7.6。我是新來的節點和異步編碼,所以我很抱歉,如果這是非常容易的。節點7.6 async等待返回數據的問題

我想運行一個函數,該函數使用特定參數調用callServer()函數,等到它完成獲取數據並將數據作爲變量返回。

這裏是我的代碼:

'use strict' 
const net = require('net') 

var formattedJson = funcRequestToJson("Server.GetStatus", false) 

doThings() 

async function doThings() { 
    var info = await callServer() 
} 

async function callServer() { 
    var client = new net.Socket() 

    client.connect(1705, '192.168.28.16',() => { 
     console.log('connected to server') 
     client.write(formattedJson) 
    }) 

    client.on('data', (data) => { 
     client.destroy() 
     //return await data 
     console.log(data.toString()) 
    }) 

    client.on('close',() => { 
    }) 
} 

// method and paramBool are always required 
// macAddress, paramKey, paramValue are required for if paramBool is true 
function funcRequestToJson(method, paramBool, macAddress, paramKey, paramValue) { 
    var objectRequest = {} 

    objectRequest[ "jsonrpc" ] = "2.0" 
    objectRequest[ "method" ] = method 
    objectRequest[ "id" ] = 0 
    if (paramBool == true) { 
     objectRequest[ "params" ] = { 
      "client": macAddress, 
      [paramKey]: paramValue 
     } 
    } 

    var json = (JSON.stringify(objectRequest) + '\r\n') 

    return json 
} 

所以我沒有申報objectRequest()的異步因爲它沒有等待服務器,但我認爲callServer()應該是異步,對不對?我知道這可以通過承諾來完成,但我想使用異步/等待,這似乎是正確的。我想要返回來自callServer()和client.on('data',(data)內部的數據,但我似乎無法弄清楚如何異步執行它。我想在那裏'd是一種創建異步函數的方法,並像我試着一樣等待(等待返回數據),但它永遠不能正常工作。

對不起,如果這是非常複雜的,但我一直在俯視在過去的一週異步節點教程和我仍然堅持。

謝謝!

+0

異步/等待依賴於使用承諾進行異步操作的代碼。因此,您需要從任何異步操作中返回一個承諾,以便與async/await一起使用它。因此,'callServer()'需要返回一個promise,在它內部的異步操作完成時解析。事實上,如果函數返回一個promise,你只能等待函數中的異步操作。 'await'使你不必在promises上編寫'.then()'處理程序,但async/await不會奇蹟般地知道異步操作何時完成。你仍然必須包裝他們的承諾。 – jfriend00

+0

啊,我不知道!正如我所說的,我是新來的異步編程方法。我不希望你必須寫我的代碼或任何東西,但是你能否指引我參考一些涉及承諾的參考資料/指南/教程?我找到了一些,但他們都很老。 –

+0

您可以從MDN開始(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)。有很多很好的在線資源。 Javascript中的承諾自第一個標準以來一直保持一致,並且全部都編碼在ES6中,因此您不應該在網上找到任何主要的不一致之處。只要避免與jQuery的Deferred或Promises有任何關係,因爲它們已經相當不規範(他們試圖在jQuery 3.x中修復它)。 – jfriend00

回答

1

異步/等待依賴於使用承諾爲異步操作的代碼。因此,你需要ŧ o從任何異步操作中返回一個承諾,以便與異步/等待一起使用它。

因此,callServer()需要返回一個承諾,在其內部的異步操作完成時解決。事實上,如果函數返回一個promise,你只能等待函數中的異步操作。 await使您不必編寫.then()處理程序的承諾,但async/await不會奇蹟般地知道異步操作何時完成。你仍然必須包裝他們的承諾。

這裏是你能怎麼做callServer()返回一個承諾的例子:

async function callServer(formattedJson) { 
    return new Promise((resolve, reject) => { 
     let client = new net.Socket() 

     client.connect(1705, '192.168.28.16',() => { 
      console.log('connected to server') 
      client.write(formattedJson) 
     }) 

     client.on('data', (data) => { 
      resolve(data); 
      client.destroy() 
     }) 

     client.on('close',() => { 
     }) 

     client.on('error', reject); 

    }); 
} 

用法示例:

try { 
    var info = await callServer(funcRequestToJson("Server.GetStatus", false)); 
} catch(e) { 
    // error here 
} 

只是爲了告訴你什麼是伺機在做什麼,在ES5(不async/await),示例的用法如下:

callServer(funcRequestToJson("Server.GetStatus", false)).then(info => { 
    // info is available here 
}).catch(err => { 
    // error here 
}); 

因此,await只是讓你避免編寫.then()處理程序。在執行代碼的內部,只是承諾解釋器會設置一個.then()處理程序,以便知道何時解決了該承諾。這是語法糖,對於異步操作來說並不是什麼神奇的東西。您仍然必須對所有異步操作使用promise。您可以使用await而不是.then(),並且您的代碼將顯示更多順序,即使它們在封面下實際上是相同的。

人們認爲await允許編寫異步代碼,就好像它是同步代碼一樣,但事實並非如此,尤其是在處理錯誤和理解併發問題時。它看起來更同步,但實際上並沒有比ES5中的.then()更同步。

並且,注意錯誤處理。在人們尋求編寫同步代碼的過程中,人們似乎完全忘記了在他們的異步操作中處理被拒絕的承諾(在使用await時使用try/catch處理)。我個人還不相信ES6在錯誤處理方面向前邁進了一步,因爲早期的跡象表明,ES6似乎鼓勵人們忘記錯誤處理或懶惰而不這樣做,而使用只是知道應該有一個.catch()的地方,因爲它是可靠的代碼。也許這只是一個學習過程,但當人們使用await時似乎是一個早期問題。

+0

我什至不能告訴你所有的幫助!有趣的是,當ES5承諾發揮作用時,您給我的等待例子不起作用。雖然我並不擔心;我要研究承諾。太感謝了! –