jfriend00 的答案是一个很好的答案,您可能只需将处理程序留在原处并在回调中使用逻辑来根据需要忽略事件。如果您真的想管理未处理的数据包,请继续阅读...
您可以从套接字内部获取回调列表,并使用它与传入的消息头进行比较。这个客户端代码就可以做到这一点。
// Save a copy of the onevent function
socket._onevent = socket.onevent;
// Replace the onevent function with a handler that captures all messages
socket.onevent = function (packet) {
// Compare the list of callbacks to the incoming event name
if( !Object.keys(socket._callbacks).map(x => x.substr(1)).includes(packet.data[0]) ) {
console.log(`WARNING: Unhandled Event: ${packet.data}`);
}
socket._onevent.apply(socket, Array.prototype.slice.call(arguments));
};
对象 socket._callbacks 包含回调,键是名称。它们前面有一个 $,因此您可以通过将 substring(1) 映射到它来将其从整个列表中删除。这会产生一个很好的干净的事件名称列表。
重要提示:通常您不应尝试从外部修改任何以下划线开头的对象成员。此外,预计其中的任何数据都是不稳定的。下划线表示它是供该对象、类或函数内部使用的。虽然这个对象不稳定,但它应该是最新的,我们可以使用它,我们不会直接修改它。
事件名称存储在 packet.data 下的第一个条目中。只需检查它是否在列表中,如果不在则发出警报。现在,当您从服务器发送事件时,客户端不知道它会在浏览器控制台中记录它。
现在您需要将未处理的消息保存在缓冲区中,以便在处理程序再次可用时播放。因此,要扩展我们之前的客户端代码...
// Save a copy of the onevent function
socket._onevent = socket.onevent;
// Make buffer and configure buffer timings
socket._packetBuffer = [];
socket._packetBufferWaitTime = 1000; // in milliseconds
socket._packetBufferPopDelay = 50; // in milliseconds
function isPacketUnhandled(packet) {
return !Object.keys(socket._callbacks).map(x => x.substr(1)).includes(packet.data[0]);
}
// Define the function that will process the buffer
socket._packetBufferHandler = function(packet) {
if( isPacketUnhandled(packet) ) {
// packet can't be processed yet, restart wait cycle
socket._packetBuffer.push(packet);
console.log(`packet handling not completed, retrying`)
setTimeout(socket._packetBufferHandler, socket._packetBufferWaitTime, socket._packetBuffer.pop());
}
else {
// packet can be processed now, start going through buffer
socket._onevent.apply(socket, Array.prototype.slice.call(arguments));
if(socket._packetBuffer.length > 0) {
setTimeout(socket._packetBufferHandler,socket._packetBufferPopDelay(), socket._packetBuffer.pop());
}
else {
console.log(`all packets in buffer processed`)
socket._packetsWaiting = false;
}
}
}
// Replace the onevent function with a handler that captures all messages
socket.onevent = function (packet) {
// Compare the list of callbacks to the incoming event name
if( isPacketUnhandled(packet) ) {
console.log(`WARNING: Unhandled Event: ${packet.data}`);
socket._packetBuffer.push(packet);
if(!socket._packetsWaiting) {
socket._packetsWaiting = true;
setTimeout(socket._packetBufferHandler, socket._packetBufferWaitTime, socket._packetBuffer.pop());
}
}
socket._onevent.apply(socket, Array.prototype.slice.call(arguments));
};
在这里,未处理的数据包被推入缓冲区并设置计时器运行。一旦给定的时间过去了,if 开始检查每个项目的处理程序是否准备好。每一个都被处理,直到全部用完或缺少一个处理程序,这会触发另一个等待。
这可以并且将会堆积未处理的调用,直到您耗尽客户端分配的内存,因此请确保这些处理程序确实在合理的时间跨度内加载。并且注意不要发送任何永远不会被处理的东西,因为它会一直尝试。
我用很长的字符串对其进行了测试,它能够推动它们通过,所以他们所说的“数据包”可能不是标准数据包。
在 Chrome 上使用 SocketIO 2.2.0 版进行测试。