我目前正在尝试在用户关闭页面时发送请求。我正在使用 onbeforeunload
事件。
标签关闭或页面刷新时触发事件。我的事件如下所示:
window.onbeforeunload = function () {
$.ajax({ //jQuery
type: "POST",
url: "offline.php",
data: {
logout: 'false'
}
});
};
offline.php(这不是完整的脚本):
...
unset($_SESSION["onpage"];
if ($_POST['logout'] == "false") {
sleep(3);
if (isset($_SESSION["onpage"]) || !empty($_SESSION["onpage"])) die();
}
...
当用户关闭页面时,脚本会取消设置在聊天页面上设置的 session 。三秒后,脚本应检查用户是否返回但检查 onpage
session 。但是,当我点击刷新按钮时,问题就来了。刷新时,页面未加载,因为三秒已完成。这导致我的整个系统被破坏。
我尝试添加 ignore_user_abort(true);
但它没有解决我的问题。还有其他方法可以使它起作用吗?
旁注:这是为了聊天。当用户关闭页面时,它应该通过“用户已离开”消息通知聊天中的其他用户。这不应在刷新时显示。当用户返回页面时,它应该通过“用户已输入”消息通知其他用户该用户已返回。
最佳答案
问题
恐怕您尝试做的事情实际上是不可能的,因为很多时候 onbeforeunload
不会被调用,由于浏览器实现、用户偏好、您的宠物斑马把你的电脑从 table 上撞下来,等等。
来自 Mozilla 的 beforeunload
文档:
Note also that various mobile browsers ignore the result of the event (that is, they do not ask the user for confirmation). Firefox has a hidden preference in about:config to do the same. In essence this means the user always confirms that the document may be unloaded.
https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
解决方案
但这并不意味着处理用户下线是不可能的,但是。
大多数聊天 Web 应用程序改为使用心跳(一种常规的类似 ping 的请求),并使用上次 ping 之间的距离来确定用户断开连接。作为附加说明,我建议允许一个比三秒更宽的窗口来确定用户断开连接,因为 ping 可能无法在三秒时间范围内完成的原因有很多。
实现策略
您有几个选项可以实现 ping。最常见的是,人们会使用 window.setTimeout
来调用 ping,这将在完成或失败时重新启动 window.setTimeout,通常会在连续失败时加倍延迟,这样您就不会发出潜在的 -重载服务。
设置 Ping 超时:
var i = 1000;
(function ping() {
$.ajax({
type: "POST",
url: "ping.php"
}).done(function() {
i = 1000;
window.setTimeout(ping, i);
}).fail(function() {
i = i * 2;
if (i > 60000) {
// We don't wait to wait longer than a minute
i = 60000;
}
window.setTimeout(ping, i);
});
}());
window.setInterval 怎么样?我的代码不会更短吗?
请不要那样做。我上面关于“阻止重载服务”的注释?如果你这样做,情况会更糟。
关于javascript - 防止浏览器卡在 AJAX 请求上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36298556/