2016-04-25 80 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