首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >防止Socket IO在Chrome、firefox和Safari移动浏览器上的非活动或未聚焦浏览器页面上切换超时

问防止Socket IO在Chrome、firefox和Safari移动浏览器上的非活动或未聚焦浏览器页面上切换超时
EN

Stack Overflow用户
提问于 2019-11-02 00:13:30
回答 1查看 4.2K关注 0票数 5

我有一个简单的聊天应用程序使用socket。非常类似的socket聊天官方演示。当用户最小化页面或打开另一个应用程序或页面时,Socket io会在所有移动浏览器上进行ping超时。

在我的web应用程序中,无论何时,用户单击移动上的chrome/firefox/safari浏览器上的文件输入上传,就会打开“电话”对话框,从厨房中选择要选择和上传的文件。在此期间(由于可见性,我的聊天页面失去了焦点),当用户正在搜索文件时,在精确30秒后,socket客户端发出ping超时,并且person聊天被断开。

在我的应用程序级别,如果socket io出于任何原因进入ping超时,我将重新连接,但这并不能解决我的问题,因为如果用户在31秒后单击1个文件,那么该图像文件就不会在聊天中发送,因为socket io在这段时间内超时,当用户的焦点回到浏览器选项卡时,重新连接需要几秒钟。所以文件上传操作丢失了,因为文件是上传的,但是socket io连接处于ping超时状态。因此,当它重新连接时,所选的文件上载永远不会发送给其他连接的用户。

我试着在用户的页面焦点熄灭时,使用以下代码进行检测,

代码语言:javascript
复制
document.addEventListener("visibilitychange", onchange);

来自是否有方法检测浏览器窗口当前是否处于活动状态?

然后,一旦页面不在焦点上,我就使用setinterval将我的自定义心跳事件发送到服务器代码。(只是为了防止socket与服务器对话以保持连接正常)。这对于桌面浏览器来说很好,但在所有移动浏览器上,只要用户页面不在焦点,即如果用户最小化浏览器,打开一个新应用程序,或去选择文件上传屏幕,socket io超时30秒后,有时甚至比这更快。

我的客户js代码:

代码语言:javascript
复制
var beating;
//function to detect if user gone out of page

//startSimulation and pauseSimulation defined elsewhere
function handleVisibilityChange() {
  //socket = this.socket;
  if (document.hidden) {
    // console.log();
    $('#logwrapper').prepend(" üser is outside \n ", socket.id);

    //emit on server after every 10 seconds
    beating = setInterval(function () {
      $('#logwrapper').prepend(" inside interval emitting");

      socket.emit('heartbeat', { data: "a" });
    }, 15000)

  } else {
    //console.log("üser is in");
    $('#logwrapper').prepend(" üser is in \n ", socket.id);
    console.log("çlearing inteval beating from visiblity");
    clearInterval(beating);
  }
}

document.addEventListener("visibilitychange", handleVisibilityChange, false);

和我的server.js代码

代码语言:javascript
复制
  //socket events for heartbeat 
    socket.on("heartbeat", function (data) {
      console.log("socket is outside ", data, socket.id);
    });
    //socket events for heartbeat , just log it so that my client remains active and keep communicating with server, to avoid socket io timeout

我也尝试过调整我的socket io服务器和客户端超时信任,但这并没有什么不同,在用户最小化移动、合唱、firefox和safari上的浏览器页面之后,socket io客户端在30秒左右后发出超时。

如何增加这个超时,以便socket连接在更长的时间内保持活动(不要平超时)?

以下是我对socket的server.js信任:

代码语言:javascript
复制
var io = require("socket.io")(
  231, {
    transports: ["websocket", "polling"]
  },
  server, {
    path: '/socket.io',
    serveClient: true,
    // below are engine.IO options
    pingInterval: 25000, //was 10k, how many ms before sending a new ping packet, => how often to send a ping
    pingTimeout: 30000, //should be above 30k to fix disconnection issue how many ms without a pong packet to consider the connection closed
    upgradeTimeout: 20000, // default value is 10000ms, try changing it to 20k or more
    agent: false,
    cookie: false,
    rejectUnauthorized: false,
    reconnectionDelay: 1000,
    reconnectionDelayMax: 5000,
    maxHttpBufferSize: 100000000 //100 mb
  }
);

我的socket io客户吐露道:

代码语言:javascript
复制
 this.socket = io.connect('https://appurl.com', {
      reconnection: true,
      reconnectionDelay: 1000,
      reconnectionDelayMax: 5000,
      reconnectionAttempts: Infinity,
      //our site options
      transports: ["polling", "websocket"],
      secure: true,
      rejectUnauthorized: false,
      forceNew: false,
      timeout: 60000
    });

基本上,在所有的移动浏览器上,只要页面脱离焦点,我的JS代码就会停止执行,每当页面再次聚焦时,JS退出就会恢复,看起来它不存在设置间隔或设置超时的问题。如何继续执行我的客户端JS代码以防止socket执行ping超时?

我还使用settimeout ( https://codepen.io/Suhoij/pen/jAxtn )尝试了类似的逻辑。

这段代码适用于所有移动浏览器的代码,即使我将手机上的页面最小化并再次返回,计时器仍在执行,但在我的应用程序上运行时相同的代码在我的代码中不起作用。为什么?当页面不在焦点时,socket是否暂停了我的所有client.js代码?还是我的逻辑不对?我还试着在每2秒向所有客户端发送一次来自我的server.js的事件,但是当页面不在移动环境中时,发射停止:/

相关套接字io问题:https://github.com/socketio/socket.io/issues/2769

EN

回答 1

Stack Overflow用户

发布于 2022-03-16 20:46:13

关于我在socket.io 4.4.1上必须做的事情

我使用管理器事件处理移动https://socket.io/docs/v4/client-api/#event-error上的断开连接。

代码语言:javascript
复制
    import io from "socket.io-client";
    socket = io(socketUrl, {
        reconnectionAttempts,
        reconnectionDelay,
    });

    //for the actual websocket having an error attempt to reconnect
    socket.io.on("error", (error) => {
        // ...
        console.log('socket io error on ' + error);
        socket = io(socketUrl, {
            reconnectionAttempts,
            reconnectionDelay,
        });
    });

    let socketArray = ['reconnect', 'reconnect_attempt', 'reconnect_error', 'reconnect_failed'];

    for(let i = 0, len = socketArray.length; i < len; i++) {
        socket.io.on(socketArray[i], (attempt) => {
            // ...
            console.log(socketArray[i] + ' socket io on ' + attempt);
        });
    }

这使得它如果websocket管理器有一个错误,它将重新连接。当我在浏览器上的套接字好,关闭我的iphone,回到浏览器,在那里它重新连接使用socket.on('connection'罚款,然后当我关闭我的手机屏幕,然后再回去,我会得到这个错误的WebSocket connection to 'wss://mysocketserver.com' failed: The operation couldn’t be completed. (kNWErrorDomainPOSIX error 53 - Software caused connection abort),通过添加socket.io.on("error",让它重新连接,然后它将正确地重新建立每一样东西。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58667207

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档