2016-04-25 76 views
1

我目前正在建立一個web應用程序,有兩個明確的用例。錯誤處理通過websockets設計dessision

  1. 來自服務器的傳統客戶端請求數據。
  2. 客戶端在服務器開始將數據推送到客戶端之後向服務器請求一個流。

目前即時通信實現1和2使用JSON消息傳遞通過WebSocket。然而,這已經證明很難,因爲我需要手工編碼很多錯誤處理,因爲客戶端並沒有等待響應。它只是發送消息,希望它能在某個時候得到答覆。 即時通訊使用Js和前端和Clojure在後端作出反應。

我對此有兩個問題。

  1. 鑑於目前的設計,通過websocket進行錯誤處理有哪些替代方案?
  2. 將UC1和UC2的websockets分開使用兩個UC會更聰明,那麼我可以在前端使用類似於fetch的東西來進行其他呼叫。

更新。 目前的問題是不知道如何通過websockets構建一個異步發送函數可以匹配發送消息和響應消息。

+1

在webSocket消息傳遞體系結構中構建請求/響應不是微不足道的。這不是自然的要求/迴應。您可能需要在每條消息和響應中使用某種消息ID,因此,當您發送消息時,您可以根據您輸入的ID確定哪條消息屬於該消息。 – jfriend00

+0

所以你會說使用休息和websockets並排更容易? – user3139545

+0

那麼,http是自然的請求/響應,它很容易使用。但是,如果您正在嘗試執行的操作,則無法通過HTTP從服務器到客戶端執行請求/響應。如果您的請求是從客戶端到服務器的,那麼HTTP和REST對於這一點來說更容易。 – jfriend00

回答

1

這是一個通過socket.io做請求/響應的方案。你可以通過簡單的webSocket來完成,但你必須自己構建一些基礎設施。這同樣庫可以在客戶端和服務器中使用:

function initRequestResponseSocket(socket, requestHandler) { 
    var cntr = 0; 
    var openResponses = {}; 

    // send a request 
    socket.sendRequestResponse = function(data, fn) { 
     // put this data in a wrapper object that contains the request id 
     // save the callback function for this id 
     var id = cntr++; 
     openResponses[id] = fn; 
     socket.emit('requestMsg', {id: id, data: data}); 
    } 

    // process a response message that comes back from a request 
    socket.on('responseMsg', function(wrapper) { 
     var id = wrapper.id, fn; 
     if (typeof id === "number" && typeof openResponses[id] === "function") { 
      fn = openResponses[id]; 
      delete openResponses[id]; 
      fn(wrapper.data); 
     } 
    }); 

    // process a requestMsg 
    socket.on('requestMsg', function(wrapper) { 
     if (requestHandler && wrapper.id) { 
      requestHandler(wrapper.data, function(responseToSend) { 
       socket.emit('responseMsg', {id: wrapper.id, data; responseToSend}); 
      }); 
     } 
    }); 
} 

這是通過包裝在包含值唯一ID的包裝對象,每發送一個信息。然後,當另一端發送它的響應時,它包含相同的id值。然後可以將該id值與該特定消息的特定回調響應處理程序進行匹配。它可以從客戶端到服務器或服務器到客戶端兩種方式工作。

您可以通過在每一端上的socket.io套接字連接上調用initRequestResponseSocket(socket, requestHandler)來使用此功能。如果你想接收請求,那麼你傳遞一個requestHandler函數,每次有請求時都會調用它。如果您只發送請求並接收響應,那麼您不必在連接的那端傳遞requestHandler。

要發送消息,並等待響應,你這樣做:

socket.sendRequestResponse(data, function(err, response) { 
    if (!err) { 
     // response is here 
    } 
}); 

如果收到請求並回送應答,那麼你這樣做:

initRequestResponseSocket(socket, function(data, respondCallback) { 
    // process the data here 

    // send response 
    respondCallback(null, yourResponseData); 
}); 

至於錯誤處理,你可以監視連接丟失,並且你可以在這段代碼中建立一個超時,這樣如果響應沒有在一定的時間內到達,那麼你會得到一個錯誤。

下面是實現一個超時不來一段時間內響應上面的代碼的擴展版本:

function initRequestResponseSocket(socket, requestHandler, timeout) { 
    var cntr = 0; 
    var openResponses = {}; 

    // send a request 
    socket.sendRequestResponse = function(data, fn) { 
     // put this data in a wrapper object that contains the request id 
     // save the callback function for this id 
     var id = cntr++; 
     openResponses[id] = {fn: fn}; 
     socket.emit('requestMsg', {id: id, data: data}); 
     if (timeout) { 
      openResponses[id].timer = setTimeout(function() { 
       delete openResponses[id]; 
       if (fn) { 
        fn("timeout"); 
       } 
      }, timeout); 
     } 
    } 

    // process a response message that comes back from a request 
    socket.on('responseMsg', function(wrapper) { 
     var id = wrapper.id, requestInfo; 
     if (typeof id === "number" && typeof openResponse[id] === "object") { 
      requestInfo = openResponses[id]; 
      delete openResponses[id]; 
      if (requestInfo) { 
       if (requestInfo.timer) { 
        clearTimeout(requestInfo.timer); 
       } 
       if (requestInfo.fn) { 
        requestInfo.fn(null, wrapper.data); 
       } 
      } 
     } 
    }); 

    // process a requestMsg 
    socket.on('requestMsg', function(wrapper) { 
     if (requestHandler && wrapper.id) { 
      requestHandler(wrapper.data, function(responseToSend) { 
       socket.emit('responseMsg', {id: wrapper.id, data; responseToSend}); 
      }); 

     } 
    }); 
} 
0

有一對夫婦在你的問題,有趣的東西和你的設計,我寧願忽略實​​現細節並查看高級架構。

您聲明您正在尋找請求數據的客戶端和響應某些數據流的服務器。兩件事情,這裏要注意:

  1. HTTP 1.1有選項發送流媒體響應(塊傳輸編碼)。如果你的用例只是發送流式響應,這可能更適合你。這不適用於你,例如想要將消息推送到沒有響應某種請求的客戶端(有時稱爲服務器端事件)。
  2. 與HTTP相反,Websockets本身並不實現某種請求 - 響應循環。你可以通過實現你自己的機制來使用協議,例如子協議WAMP正在做。

正如你發現的那樣,實現你自己的機制帶來了陷阱,那就是HTTP有明顯的優勢。鑑於你的問題中陳述的要求,我會選擇HTTP流式方法,而不是實現自己的請求/響應機制。

+0

服務器將在沒有請求的情況下將消息推送到客戶端。這就是爲什麼即時通訊考慮使用rest ans ws或實現發送響應邏輯和只有ws。 – user3139545