【问题标题】:Are there any window events triggered if user "pulls the plug" and shuts down their computer?如果用户“拔掉插头”并关闭计算机,是否会触发任何窗口事件?
【发布时间】:2018-08-10 10:54:33
【问题描述】:

我有一个网站,我只希望客户端一次能够有 1 个 WebSocket 连接(当他们打开另一个选项卡而已经有另一个连接显示时,我会向他们显示一个错误)。

我正在开发一个客户端解决方案,当请求连接时,我将本地存储中的标志更新为真(如果标志已经为真,则不会请求)然后我监听 beforeunload 事件如果该选项卡具有打开的连接,则将本地存储标志设置为 false。

这似乎工作得很好,除了当用户突然关闭他们的计算机并且因此 beforeunload 永远不会触发的边缘情况,所以当他们重新打开他们的计算机时,本地存储标志卡在 true 并且他们没有卡住能够在任何选项卡中连接。

是否有在关机前调用的事件,我可以将本地存储标志设置为 false?

如果没有,客户端是否有另一种解决方案来跟踪它在所有选项卡中只有 1 个 WebSocket 连接,以便如果已经有一个连接,它可以阻止连接?

window.addEventListener('beforeunload', this.setFlagToFalse);

【问题讨论】:

  • 没有。没有电源的计算机无法在该计算机上的浏览器中触发事件 - 您需要更智能的服务器端
  • 我知道服务器端是理想的解决方案,但是对于这个用例,它不是关键任务,我想要一个客户端解决方案。我想要的只是一次打开 1 个 websocket 连接(如果 websocket 连接,则不要连接),我认为必须离开才能实现这个客户端,除了这个单一的边缘情况外,我的解决方案效果很好.
  • 也许您应该尝试了解 chrome 如何发现它从崩溃中恢复(或您提到的完全相同的情况)并为用户提供restore tabs 的选项。不知道其他浏览器也是如此。 PS:也许标志应该是您的 websocket 连接&在这种情况下您应该尝试重用它。如果 websocket 无效/报错,尝试重新连接?
  • 使用时间戳而不是标志
  • 为什么不能定期从其他选项卡请求新的 websocket 连接,如果用户已经有另一个连接,则返回带有重试时间戳的错误?

标签: javascript html reactjs


【解决方案1】:

正如 Jaromanda 的评论中正确指出的那样,没有电源的计算机无法向浏览器发出事件(甚至不再存在......)。

但是,解决根本问题的一种方法是监听 storage 事件。

当另一个窗口对该存储进行任何修改时,此事件将在共享同一存储区域的所有 Windows 中触发。

因此,我们可以将其用作在同一域中的 Windows 之间几乎实时通信的一种手段。这意味着您不必让您的标志保持最新,您现在可以直接知道其他窗口是否已经处于活动状态。

这是一个基本的实现。我会让您享受使它更适合您的需求的乐趣。

let alone = true; // a flag to know if we are alone
onstorage = e => { // listen to the storage event
  if(e.key === 'am_I_alone') {
    if(e.newValue === 'just checking') { // someone else is asking for permission
      localStorage.am_I_alone = 'false'; // refuse
    }
    else if(e.newValue === 'false') { // we've been refused access
      alone = false;
    }
  }
};

localStorage.am_I_alone = 'just checking'; // trigger the event on the other Windows

setTimeout(()=>{ // let them a little time to answer
  if(alone) { // no response, we're good to go
    // so the next one can trigger the event
    localStorage.am_I_alone = "true";
    startWebSocket();
  }
  else { // we've been rejected...
    error();
  }
}, 500);

Live Plnkr

【讨论】:

  • 喜欢这个解决方案。现在将实施,看看它如何保持。一个问题。为什么是 500 毫秒?我不应该让用户只等待 50 毫秒吗? 99.999% 的时间 50 毫秒就足够了,对吧?如果没有必要,宁愿不让用户额外等待。
  • 只是安全... 500 确实很大,但模糊的窗口会受到限制,因此事件可能不会在 50 毫秒之前触发。在页面加载事件结束时有 200 毫秒,你应该没问题。你甚至可以在 onstorage 事件处理程序中添加另一个 else ,这样当 master 错误地看到另一个 Window 虽然它是单独的,它会说它实际上不是并且另一个窗口关闭连接。但正如我所说,“我会让你享受让它更适合你的需求的乐趣。”
猜你喜欢
  • 2013-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多