关闭Chrome窗口未在卸载事件处理程序中使用sendBeacon发送数据

问题描述

我正在尝试在窗口关闭时发送数据,以防止2个人编辑和覆盖彼此的数据。目前,我正在卸载事件处理程序中使用sendbeacon

FireFox:

  • 刷新:有效
  • 返回按钮:有效
  • 关闭窗口:有效

Chrome浏览器:

  • 刷新:有效
  • 返回按钮:有效
  • 关闭窗口:不起作用

这是我的代码

function sendDataOnClose(edit,trans){

    var url = "../../save.PHP"; //This has a post request handler and works properly with other functions for saving data

    const data = JSON.stringify
    ({
      "translations": trans,"edit": edit
    });

    navigator.sendbeacon(url,data);
  }

function handleClose(){
    if(edit){
      console.log("sending a false when edit is: "+ edit)
      sendDataOnClose(false,translations);
    }
  }

window.addEventListener('unload',handleClose); 

解决方法

MDN 上的最新 sendBeacon 文档指出“navigator.sendBeacon() 方法通过 HTTP 异步发送少量数据到 Web 服务器。它旨在与visibilitychange 事件(但不适用于 unload 和 beforeunload 事件)。”

要像建议的那样使用 visibilitychange 事件,您可以

document.addEventListener('visibilitychange',function() {
  if (document.visibilityState === 'hidden') {
    navigator.sendBeacon(handleClose);
  }
});

我在尝试在 unload 事件上发送数据时遇到了类似的问题。用户群都在桌面上吗?移动设备不能可靠地触发 unload 事件。 Page Lifecycle API 提供可见性更改事件和 pagehide 事件,它们可以一起使用以更接近您想要的结果。

页面生命周期 API 尝试通过以下方式解决此问题: 在网络上引入和标准化生命周期状态的概念。 定义新的系统启动状态,允许浏览器限制隐藏或非活动选项卡可以使用的资源。 创建新的 API 和事件,允许 Web 开发人员响应这些新的系统启动状态之间的转换。 source

您遇到的问题可能更像是一个与浏览器如何暂停页面或完全丢弃页面无关的问题。不幸的是,浏览器在如何实现这一点上并不统一,而且更复杂的是,桌面和移动设备上的行为有所不同。

如果您有兴趣,有几个线程可以更深入地探讨这个问题。在浏览器对此进行标准化之前,我不确定是否有一个简单的答案,例如 “使用 x 事件”

Issue filed on Page Visibility

Issue on MDN's strints about sendBeacon

,

感谢黑客,出于安全原因删除了许多其他内容。

我注意到你的问题也有 PHP 标签;我会给你一个,不是好主意,而是一个实用的主意。避免关闭页面处理甚至 JavaScript 或框架只是用 JavaScript 发布一个表数据库,您在其中存储 time() 和目标 id,然后如果超时可能超过 30 秒,那么您将从表中删除那些东西,并且您会知道该页面仍然无法正常工作(翻译:使用服务器“在线用户”的想法(不好但必要的想法,就像任何会在应用中产生大量流量的东西一样)。

在侧客户端的 JavaScript 中使用这些是个坏主意,你会为利用你的应用程序的坏人打开大门。