未处理的socket.io事件会发生什么?

4
socket.io是否会忽略或丢弃未处理的消息?
我之所以问这个问题是因为有一个客户端有多种状态。每种状态都有自己的socket处理程序。在不同的时刻,服务器会通知客户端状态发生改变,并发送几个与状态相关的消息。
但是!客户端需要一些时间来更改状态并设置新的处理程序。在这种情况下,客户端可能会错过一些消息...因为此时还没有处理程序。如果我理解正确,对于客户端来说,未处理的消息将会丢失。
也许我没有理解概念或者做错了什么...如何解决这些问题?
2个回答

7

未处理的消息将被忽略。这就像事件发生时没有事件侦听器一样。套接字接收到消息,找不到处理程序,因此不会对其进行任何操作。

您可以通过始终安装处理程序,然后根据其他状态在处理程序中决定是否对消息进行任何操作来避免丢失消息。


2

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));
};

这里未处理的数据包被推入缓冲区,并启动定时器。一旦经过了指定的时间,它开始检查每个项的处理程序是否准备就绪。每一个都会被处理,直到所有的处理程序都用完或者缺少处理程序,这将触发另一个等待。

这可能会导致未处理的调用堆积,直到超出客户端分配的内存,因此请确保这些处理程序在合理的时间范围内加载。并且要注意不要发送任何永远无法处理的内容,因为它会一直尝试。

我使用SocketIO版本2.2.0在Chrome上进行了测试,即使使用非常长的字符串也能够顺利传输,因此他们所谓的“数据包”可能不是标准的数据包。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接