关闭 Chrome 窗口未在卸载事件处理程序中使用 sendBeacon 发送数据
Posted
技术标签:
【中文标题】关闭 Chrome 窗口未在卸载事件处理程序中使用 sendBeacon 发送数据【英文标题】:Closing Chrome window not sending data with sendBeacon in unload event handler 【发布时间】:2021-02-22 15:56:46 【问题描述】:我正在尝试在窗口关闭时发送数据,以防止 2 个人编辑和覆盖彼此的数据。目前我在卸载事件处理程序中使用 sendBeacon。
火狐:
刷新:作品 返回按钮:有效 关闭窗口:作品铬:
刷新:作品 返回按钮:有效 关闭窗口:不起作用这是我的代码
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);
【问题讨论】:
即使文档显示unload and beforeunload aren’t the right events to use with sendBeacon. Instead, use visibilitychange.
它也不能在关闭 visibilitychange
事件时起作用!
@webdevtrev 它适用于所有主流浏览器的最新版本,我最近测试过。你可以查看这个帖子:https://***.com/a/69955104/1786360
【参考方案1】:
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
您遇到的问题可能更多的是一个问题,而不是浏览器如何暂停页面或完全丢弃它们。不幸的是,浏览器在如何做到这一点上并没有统一,而且更复杂的是,桌面和移动设备上的行为不同。
如果您有兴趣,有几个线程可以深入探讨这个问题。在浏览器对此进行标准化之前,我不确定是否有一个简单的答案,例如 "use x event"。
Issue filed on Page Visibility
Issue on MDN's strints about sendBeacon
【讨论】:
pagehide
或 visbilitychange
不会在标签关闭时触发。那就是问题所在。我需要任何在窗口关闭时触发但没有任何工作的事件。
请将其拼写为“可见性”而不是“可见性”。【参考方案2】:
感谢黑客,出于安全原因,许多其他内容都被删除了。
我注意到您的问题也有 PHP 标记;我会给你一个,不是好主意,而是一个实用的。避免关闭页面处理,即使是 javascript 或框架只是使用 JavaScript 发布一个表数据库,您在其中存储 time()
和一个目标 ID,然后如果超时可能超过您设置的 30 秒,那么您将从表中删除这些东西,然后您会知道该页面仍然无法工作(翻译:使用服务器“在线用户”的想法(糟糕但必要的想法,就像任何东西都会在应用程序中产生大量流量)。
在侧客户端的 JavaScript 中使用这些是个坏主意,您会为利用您的应用程序的坏人打开大门。
【讨论】:
我已经在服务器端超时了。我想在用户关闭页面时结束计时器。 @Brackets 那就简单多了!超时应自行到期。:每次用户目标或其他用户在脚本启动时输入时,您都应检查所有超时并删除缺少的超时,您是目标开始时间,因此您可以通过验证在超时时关闭服务器页面上的处理开始和停止引用当前 php time();根据超时差异 请编辑答案以包含这个想法。 @Janos Vinceller 我可以编写一个 php mysql 脚本来演示“在线用户”启动然后停止 php 验证程序处理程序,但不会是我 100% 想到的(在我的情况下,这些情况的代码是在我需要它之前出现,在我的框架中,所以我不会检查 *** 一个我知道的答案)。关于防止黑客攻击部分,我不会再发布一些东西可以给我试图在我的应用程序中停止的伙伴提供想法..所以如果你不喜欢这个答案,我可以删除它以上是关于关闭 Chrome 窗口未在卸载事件处理程序中使用 sendBeacon 发送数据的主要内容,如果未能解决你的问题,请参考以下文章
为啥我不能使用 jQuery 从卸载事件处理程序触发 AJAX 请求?