这是一个通过 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});
});
}
});
}