在 x 秒/第一次尝试获得响应失败后,socket.io 停止重新发出事件 [英] socket.io stop re-emitting event after x seconds/first failed attempt to get a response

查看:15
本文介绍了在 x 秒/第一次尝试获得响应失败后,socket.io 停止重新发出事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到每当我的服务器离线时,我将它切换回在线状态,它会收到大量套接字事件,这些事件在服务器关闭时被触发.(事件......现在已经过时了).

I noticed that whenever my server is offline, and i switch it back online, it receives a ton of socket events, that have been fired while server was down. ( events that are ... by now outdated ).

有没有办法阻止 socket.io 在 x 秒内没有收到响应后重新发出事件?.

Is there a way to stop socket.io from re-emitting the events after they have not received a response for x seconds ?.

推荐答案

当开源库的所有其他方法都失败时,你去研究代码,看看你能找到什么.在用 socket.io 源代码做了一些事情之后......

When all else fails with open source libraries, you go study the code and see what you can figure out. After spending some time doing that with the socket.io source code...

问题的关键似乎是这段代码 socket.emit() 中的noreferrer">此处:

The crux of the issue seems to be this code that is here in socket.emit():

  if (this.connected) {
    this.packet(packet);
  } else {
    this.sendBuffer.push(packet);
  }

如果socket未连接,所有通过.emit()发送的数据都缓存在sendBuffer中.然后,当套接字再次连接时,我们看到:

If the socket is not connected, all data sent via .emit() is buffered in the sendBuffer. Then, when the socket connects again, we see this:

Socket.prototype.onconnect = function(){
  this.connected = true;
  this.disconnected = false;
  this.emit('connect');
  this.emitBuffered();
};

Socket.prototype.emitBuffered = function(){
  var i;
  for (i = 0; i < this.receiveBuffer.length; i++) {
    emit.apply(this, this.receiveBuffer[i]);
  }
  this.receiveBuffer = [];

  for (i = 0; i < this.sendBuffer.length; i++) {
    this.packet(this.sendBuffer[i]);
  }
  this.sendBuffer = [];
};

所以,这完全解释了为什么它会在连接断开时缓冲所有发送的数据,然后在重新连接时将其全部发送.

So, this fully explains why it buffers all data sent while the connection is down and then sends it all upon reconnect.

现在,关于如何阻止它发送这些缓冲数据,这里有一个理论,我将在今晚晚些时候有更多时间时尝试测试.

Now, as to how to prevent it from sending this buffered data, here's a theory that I will try to test later tonight when I have more time.

两件事看起来像是一个机会.套接字在发送缓冲数据之前通知 connect 事件,sendBuffer 是套接字的公共属性.因此,看起来您可以在客户端代码中执行此操作(在连接时清除缓冲区):

Two things look like they present an opportunity. The socket notifies of the connect event before it sends the buffered data and the sendBuffer is a public property of the socket. So, it looks like you can just do this in the client code (clear the buffer upon connect):

// clear previously buffered data when reconnecting
socket.on('connect', function() {
    socket.sendBuffer = [];
});

我刚刚测试了它,它工作得很好.我有一个客户端套接字,每秒向服务器发送一个递增的计数器消息.我将服务器关闭 5 秒钟,然后当我在添加此代码之前重新启动服务器时,所有排队的消息都到达服务器.没有遗漏任何计数.

I just tested it, and it works just fine. I have a client socket that sends an increasing counter message to the server every second. I take the server down for 5 seconds, then when I bring the server back up before adding this code, all the queued up messages arrive on the server. No counts are missed.

当我添加上面的三行代码时,服务器关闭时发送的任何消息都不会发送到服务器(从技术上讲,它们在发送之前会从发送缓冲区中清除).它有效.

When, I then add the three lines of code above, any messages sent while the server is down are not sent to the server (technically, they are cleared from the send buffer before being sent). It works.

仅供参考,另一种可能是在套接字未连接时不调用 .emit().因此,您可以创建自己的函数或方法,当套接字实际连接时,它只会尝试 .emit(),因此任何东西都不会进入 sendBuffer.

FYI, another possibility would be to just not call .emit() when the socket is not connected. So, you could just create your own function or method that would only try to .emit() when the socket is actually connected, thus nothing would ever get into the sendBuffer.

Socket.prototype.emitWhenConnected = function(msg, data) {
    if (this.connected) {
        return this.emit(msg, data);
    } else {
        // do nothing?
        return this;
    }
}

或者,更危险的是,您可以覆盖 .emit() 以使其以这种方式工作(不是我的建议).

Or, more dangerously, you could override .emit() to make it work this way (not my recommendation).

这篇关于在 x 秒/第一次尝试获得响应失败后,socket.io 停止重新发出事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆