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

时间:2015-09-28 05:36:59

标签: javascript node.js socket.io-1.0

socket.io是否忽略\删除它们? 我问这个的原因如下。 有一个客户有几个州。每个州都有自己的套接字处理程序。在不同时刻,服务器通知客户端状态更改,之后发送多个状态相关消息。 但!客户端需要一些时间来更改状态并设置新的处理程序。在这种情况下,客户端可能会错过一些消息...因为此刻没有处理程序。 如果我理解正确,未经处理的消息将丢失给客户端。

可能是我错过了这个概念,或者做错了......如何解决这个问题?

2 个答案:

答案 0 :(得分:6)

未处理的邮件会被忽略。就像事件发生时一样,事件没有事件监听器。套接字接收msg并且找不到它的处理程序,因此它没有任何反应。

您可以通过始终安装处理程序然后在处理程序中决定是否对消息执行任何操作来避免丢失消息。

答案 1 :(得分:0)

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版进行了测试。