jfriend00的回答很好,你可能只需要保留处理程序并在回调中使用逻辑来忽略不需要的事件。如果你真的想管理未处理的数据包,请继续阅读...
你可以从套接字内部获取回调列表,并将其与传入消息头进行比较。这个客户端代码就是这样做的。
socket._onevent = socket.onevent;
socket.onevent = function (packet) {
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的第一个条目中。只需检查它是否在列表中,如果不在,则引发警报。现在,当您从服务器发送事件时,客户端不知道它,它将在浏览器控制台中进行记录。
现在,您需要将未处理的消息保存在缓冲区中,以在再次可用处理程序时播放。因此,让我们扩展之前的客户端代码...
socket._onevent = socket.onevent;
socket._packetBuffer = [];
socket._packetBufferWaitTime = 1000;
socket._packetBufferPopDelay = 50;
function isPacketUnhandled(packet) {
return !Object.keys(socket._callbacks).map(x => x.substr(1)).includes(packet.data[0]);
}
socket._packetBufferHandler = function(packet) {
if( isPacketUnhandled(packet) ) {
socket._packetBuffer.push(packet);
console.log(`packet handling not completed, retrying`)
setTimeout(socket._packetBufferHandler, socket._packetBufferWaitTime, socket._packetBuffer.pop());
}
else {
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;
}
}
}
socket.onevent = function (packet) {
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));
};
这里未处理的数据包被推入缓冲区,并启动定时器。一旦经过了指定的时间,它开始检查每个项的处理程序是否准备就绪。每一个都会被处理,直到所有的处理程序都用完或者缺少处理程序,这将触发另一个等待。
这可能会导致未处理的调用堆积,直到超出客户端分配的内存,因此请确保这些处理程序在合理的时间范围内加载。并且要注意不要发送任何永远无法处理的内容,因为它会一直尝试。
我使用SocketIO版本2.2.0在Chrome上进行了测试,即使使用非常长的字符串也能够顺利传输,因此他们所谓的“数据包”可能不是标准的数据包。