尽管收到了来自服务器的消息,但 Chrome 的 onmessage() 不会在重新连接后立即触发

Posted

技术标签:

【中文标题】尽管收到了来自服务器的消息,但 Chrome 的 onmessage() 不会在重新连接后立即触发【英文标题】:Chrome's onmessage() does not fire immediately after reconnect, despite receiving a message from the server 【发布时间】:2019-11-04 10:20:46 【问题描述】:

我目前正在尝试在 chrome 和 NodeJS 服务器之间创建一个 websocket。 Node 服务器使用的是ws 插件,而我使用的是 Chrome 的默认 websocket 处理程序。

这是我的服务器代码行:

wss.on('connection', function connection(ws) 
  ws.id = uuid();
  let response = 'type': 'uuid','data': ws.id;
  ws.send(JSON.stringify(response));
);

我的客户代码:

//Listens for new messages
connection.onmessage = function(e) 
  let data = JSON.parse(e.data);
  console.log(data.data);

我的期望:每次创建连接时,服务器都会为客户端生成一个 UUID,然后客户端将其打印到控制台。当连接断开并且客户端重新连接时,服务器会向客户端发送一个新的 UUID。

发生了什么:服务器在创建连接时为客户端生成一个 UUID,然后客户端将其打印到控制台。但是,当服务器宕机并重新启动,并且客户端重新建立连接时,服务器确实会向客户端发送一个新的 UUID,但 chrome 并没有接收到它。

任何帮助将不胜感激。谢谢!

编辑:这就是我重新连接到服务器的方式

//Reconnect to server
setInterval(function() 
  if (connection.readyState !== WebSocket.OPEN) 
    reconnect = false;
    connection.close();
    console.log("Disconnected from server. Retrying...");
    connection = new WebSocket(server);
   else 
    if (!reconnect) 
        reconnect = true;
        console.log("Reconnected to server.");
    
  
, 1000);

编辑2:修改了代码,还是不行:

//Webhook
//On connection open
connection.onopen = function() 
  console.log("Connected to server");
  reconnect = "";
  //Reconnect to server if disconnected
  connection.onclose = function(e) 
    console.log("Connection closed, reconnecting...");
    //Retry every second
    reconnect = setInterval(function() 
        if (connection.readyState !== WebSocket.OPEN) 
            connection.close();
            console.log("Connecting to server...");
            connection = new WebSocket(server);
        
    , 1000);
  

onopen() 也不会在重新连接时触发,因此客户端会在断开连接后每秒尝试重新连接,并且永远不会停止。

【问题讨论】:

如果客户端重新连接到服务器,您确定在新连接上设置了onmessage 监听器吗?您能否在问题中包含重新连接处理? 实现我会尽快回复你@Seblor @Seblor 我该怎么做呢?我是否将onmessage 包装成onopen?我添加了我重新连接到上面主要问题的方式。 没错。当 websocket 打开它的连接时,你应该初始化所有的监听器。 另外,您可以向onclose 事件添加侦听器,而不是使用 setInterval 来检查连接是否仍然存在,该事件将在服务器关闭(或崩溃)时触发,然后尝试重新连接(如果您想多次尝试以防第一次失败,可以使用 setinterval )。这在性能方面会更好,因为您不必每次都执行相同的检查。 【参考方案1】:

我找到了解决办法

//Webhook
function connect() 
  //Attempt to connect to server
  if (firstConnect) 
    console.log("Connecting to server...");
    connection = new WebSocket(server);
   else 
    if (connection.readyState !== WebSocket.OPEN) 
      connection.close();
      console.log("Connecting to server...");
      connection = new WebSocket(server);
    
  

  //On connection open
  connection.onopen = function() 
    firstConnect = false;
    console.log("Connected to server");
    clearInterval(reconnect);
  

  //Listens for new messages
  connection.onmessage = function(e) 

 

   //Reconnect to server if disconnected
   connection.onclose = function(e) 
    console.log("Connection closed, reconnecting...");
    connect();
  

当您创建新的套接字连接时,chrome 会反复尝试自行连接,直到超时。超时将触发connection.onclose,然后调用connect()

通过将其全部嵌套在 connect() 中,事件处理程序将每次都挂接到新的 websocket 连接上。此外,您不需要setInterval(),从而避免任何性能问题。

经过测试的浏览器:Chrome、Opera、Safari

【讨论】:

以上是关于尽管收到了来自服务器的消息,但 Chrome 的 onmessage() 不会在重新连接后立即触发的主要内容,如果未能解决你的问题,请参考以下文章

找出 Profobuf 消息的类型(Google Chrome 同步)

尽管我使用了有效的令牌,但 Laravel Passport 得到未经身份验证的响应

“未经检查的 runtime.lastError:消息端口在收到响应之前关闭。” Chrome 扩展程序

网络推送通知未在 Chrome 中显示

Paypal 中某些 IPN 消息的无效响应

尽管设置了 CHROME_EXECUTABLE 环境变量,但 Chrome 对“颤振模拟器”不可见