简体   繁体   English

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

[英]What happens with unhandled socket.io events?

Does socket.io ignore\\drop them? socket.io会忽略\\删除它们吗? The reason why Im asking this is the following. 我问这个的原因如下。 There is a client with several states. 有一个客户有几个州。 Each state has its own set of socket handlers. 每个州都有自己的套接字处理程序。 At different moments server notifies the client of state change and after that sends several state dependent messages. 在不同时刻,服务器通知客户端状态更改,之后发送多个状态相关消息。 But! 但! It takes some time for the client to change state and to set new handlers. 客户端需要一些时间来更改状态并设置新的处理程序。 In this case client can miss some msgs... because there are no handlers at the moment. 在这种情况下,客户端可能会错过一些消息...因为此刻没有处理程序。 If I understand correctly unhandled msgs are lost for client. 如果我理解正确,未经处理的消息将丢失给客户端。

May be I miss the concept or do smth wrong... How to hanle this issues? 可能是我想念这个概念或做错了......如何处理这个问题?

Unhandled messages are just ignored. 未处理的消息只是被忽略。 It's just like when an event occurs and there are no event listeners for that event. 就像事件发生时一样,事件没有事件监听器。 The socket receives the msg and doesn't find a handler for it so nothing happens with it. 套接字接收msg并且没有找到它的处理程序,因此它没有任何反应。

You could avoid missing messages by always having the handlers installed and then deciding in the handlers (based on other state) whether to do anything with the message or not. 您可以通过始终安装处理程序,然后在处理程序(基于其他状态)中决定是否对消息执行任何操作来避免丢失消息。

jfriend00's answer is a good one, and you are probably fine just leaving the handlers in place and using logic in the callback to ignore events as needed. jfriend00的答案是一个很好的答案,你可能只是把处理程序放在适当位置并使用回调中的逻辑来根据需要忽略事件。 If you really want to manage the unhandled packets though, read on... 如果你真的想管理未处理的数据包,请继续阅读......

You can get the list of callbacks from the socket internals, and use it to compare to the incoming message header. 您可以从套接字内部获取回调列表,并使用它来与传入的消息头进行比较。 This client-side code will do just that. 这个客户端代码就是这样做的。

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

The object socket._callbacks contains the callbacks and the keys are the names. 对象socket._callbacks包含回调,键是名称。 They have a $ prepended to them, so you can trim that off the entire list by mapping substring(1) onto it. 他们有一个$前置,所以你可以通过将substring(1)映射到它上来修剪整个列表。 That results in a nice clean list of event names. 这导致了一个很好的清单事件名称列表。

IMPORTANT NOTE: Normally you should not attempt to externally modify any object member starting with an underscore. 重要说明:通常,您不应尝试从外部修改以下划线开头的任何对象成员。 Also, expect that any data in it is unstable. 此外,期望其中的任何数据都不稳定。 The underscore indicates it is for internal use in that object, class or function. 下划线表示它适用于该对象,类或函数的内部使用。 Though this object is not stable, it should be up to date enough for us to use it, and we aren't modifying it directly. 虽然这个对象不稳定,但它应该是最新的,我们可以使用它,我们不会直接修改它。

The event name is stored in the first entry under packet.data. 事件名称存储在packet.data下的第一个条目中。 Just check to see if it is in the list, and raise the alarm if it is not. 只需检查它是否在列表中,如果不是,则发出警报。 Now when you send an event from the server the client does not know it will note it in the browser console. 现在,当您从服务器发送事件时,客户端不知道它将在浏览器控制台中记录它。

Now you need to save the unhandled messages in a buffer, to play back once the handlers are available again. 现在,您需要将未处理的消息保存在缓冲区中,以便在处理程序再次可用时进行回放。 So to expand on our client-side code from before... 所以要扩展我们以前的客户端代码......

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

Here the unhandled packets get pushed into the buffer and a timer is set running. 这里未处理的数据包被推入缓冲区并且计时器被设置为运行。 Once the given amount of time has passed, if starts checking to see if the handlers for each item are ready. 一旦给定的时间量过去,如果开始检查每个项目的处理程序是否准备就绪。 Each one is handled until all are exhausted or a handler is missing, which trigger another wait. 每个都被处理,直到所有用尽或处理程序丢失,这会触发另一个等待。

This can and will stack up unhandled calls until you blow out the client's allotted memory, so make sure that those handlers DO get loaded in a reasonable time span. 这可以并且将堆叠未处理的调用,直到您吹掉客户端分配的内存,因此请确保这些处理程序在合理的时间跨度内加载。 And take care not to send it anything that will never get handled, because it will keep trying forever. 并注意不要发送任何永远不会被处理的东西,因为它将永远尝试。

I tested it with really long strings and it was able to push them through, so what they are calling 'packet' is probably not a standard packet. 我用很长的字符串测试它并且它能够推动它们通过,所以它们所谓的“数据包”可能不是标准数据包。

Tested with SocketIO version 2.2.0 on Chrome. 在Chrome上使用SocketIO版本2.2.0进行测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM