错误处理websockets一个设计dessision

时间:2016-04-25 04:53:58

标签: javascript rest clojure architecture websocket

我目前正在构建一个有两个明确用例的webapp。

  1. 来自服务器的传统客户端请求数据。
  2. 客户端在服务器开始向客户端推送数据后请求来自服务器的流。
  3. 目前我正在使用json消息传递websocket来实现1和2。然而,事实证明这很难,因为我需要手动编码大量的错误处理,因为客户端没有等待响应。它只是发送消息,希望它有时会得到答复。 我使用Js并在前端和后端的Clojure上做出反应。

    我有两个问题。

    1. 鉴于目前的设计,有哪些替代方案可以通过websocket进行错误处理?
    2. 使用UC1的休息和UC2的websockets分割两个UC会更聪明吗?然后我可以在前端使用fetch之类的东西进行休息呼叫。
    3. 更新。 目前的问题是不知道如何通过websockets构建异步发送功能可以匹配发送消息和响应消息。

2 个答案:

答案 0 :(得分: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});
            });

        }
    });
}

答案 1 :(得分:0)

您的问题和设计中有一些有趣的东西,我更喜欢忽略实现细节并查看高级架构。

您声明您正在寻找一个请求数据的客户端和一个响应某些数据流的服务器。这里有两点需要注意:

  1. HTTP 1.1具有发送流式响应的选项( Chunked transfer encoding )。如果您的用例仅是发送流媒体响应,那么这可能更适合您。当您例如,这不成立想要将消息推送到不响应某种请求的客户端(有时称为服务器端事件)。
  2. 与HTTP相反,Websockets本身并不实现某种请求 - 响应周期。您可以通过实现自己的机制来使用协议,例如,子协议WAMP正在做。
  3. 正如您所知,实现自己的机制带来了陷阱,这就是HTTP具有明显优势的地方。鉴于您的问题中陈述的要求,我会选择HTTP流方法,而不是实现您自己的请求/响应机制。