我正在尝试在用户关闭页面时发送请求。我正在使用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();
}
...
当用户关闭页面时,脚本会取消设置聊天页面上设置的会话。三秒钟后,脚本应检查用户是否已返回但是检查onpage
会话。但是,当我按下刷新按钮时会出现问题。刷新时,页面无法加载,因为三秒钟已完成。这导致我的整个系统被破坏。
我尝试添加ignore_user_abort(true);
,但它没有解决我的问题。有没有其他办法让这个工作?
旁注:这是聊天。当用户关闭页面时,它应该通过"用户已经离开"来通知聊天中的其他用户。信息。这不应该在刷新时显示。当用户返回该页面时,它应该通知其他用户该用户已经返回了"用户已经输入了"消息。
答案 0 :(得分:7)
我担心你尝试做的事情真的不可能,因为有很多次SELECT count(*) AS ct, reason_list
FROM (
SELECT sort(array_agg(reason_id)) AS reason_list
FROM activity_reason2
GROUP BY activity_id
) ar2
GROUP BY reason_list
ORDER BY ct DESC, reason_list;
因为浏览器的实施而无法调用,用户偏好,你的宠物斑马将你的电脑从桌子上敲下来等等。
来自Mozilla的onbeforeunload
文档:
另请注意,各种移动浏览器会忽略事件的结果(即,他们不会要求用户进行确认)。 Firefox在about:config中有一个隐藏的首选项来做同样的事情。实质上,这意味着用户始终确认可以卸载文档。
Storing and comparing unique combinations
大多数聊天Web应用程序使用心跳(常规类似ping的请求),并使用上次ping之间的距离来确定用户断开连接。另外需要注意的是,我建议允许使用比3秒更宽的窗口来确定用户断开连接,因为有很多原因导致ping可能无法在三秒钟内完成。
您有几个选项可以实现ping。最常见的是,人们将使用beforeunload
来调用ping,这将在完成或失败时重新启动window.setTimeout,通常会使连续失败的延迟加倍,因此您不会阻止可能过载的服务。
window.setTimeout
请不要这样做。我的上述说明"禁止超载服务"?如果你那样做会更糟。
答案 1 :(得分:1)
您真的不应指望onbeforeunload
或beforeunload
,因为浏览器不应该在用户关闭您的网页之前代表您做某事。如果确实如此,它将为你永远无法关闭页面的恶意代码开辟一条完整的攻击途径(想想去一个torrent网站并且每次点击任何DOM元素时都会弹出2个页面,现在每次都是用户尝试关闭选项卡,启动递归循环并阻止他们离开而不通过任务管理器杀死浏览器。)
大多数聊天客户端都使用心跳系统,客户端每隔x秒自动ping一次服务器。这种方法有效 - 但成本高,效率低。您被迫不断打开和关闭新连接,只是为了告诉服务器您仍在使用。
构建聊天系统之类的现代方法是使用网络套接字。这些是服务器在Web浏览器和服务器之间建立的持久连接。在传统的Web页面上,服务器始终对客户端所做的事情做出反应。客户端发出请求,服务器响应;这个过程一遍又一遍地重复着。服务器永远不会告诉客户端要做什么,然后等待客户端响应。使用Web套接字,我们有一个管道,允许通过双向通信连续开放连接,而不是使用这种单向通信通道。
这不是一项微不足道的任务。为了获得一些基本的功能,你需要编写大量的样板代码。但好消息是你不必这样做。有几个第三方JavaScript SDK /后端服务为您封装了所有底层浏览器实现逻辑,并为您提供了一个简单,清晰的界面。想想他们与Web套接字的关系,就像jQuery对纯JavaScript的看法一样。它们为您标准化所有内容,因此您不必担心编写低级Web套接字实现并同步跨浏览器兼容性。
我最喜欢的网络套接字服务之一是Firebase。巧合的是,他们在网站上展示的demo project是使用其服务提供的网络套接字支持构建的实时聊天应用程序。如果您想要Firebase,可以将Firebase设置为独立的数据库源。或者它可以简单地用作传统SQL数据库(通过RESTful API与之通信)和客户端设备(浏览器,应用程序等)之间的通信媒介。
答案 2 :(得分:0)
我想指出的是,正如其他人所说,在页面卸载事件上执行AJAX请求是非常不可靠的。
但是,您可能对Navigator.sendBeacon()
感兴趣相关摘录:
此方法解决了分析和诊断代码的需求,这些代码通常在卸载文档之前尝试将数据发送到Web服务器。
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
这是实验性的,但一旦完全支持,就应该做你想做的事。
答案 3 :(得分:0)
当页面离开时,AJAX会被切断。
您需要改为使用navigator.sendBeacon()
。
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
window.addEventListener('unload', function () {
navigator.sendBeacon("offline.php", {
logout: 'false'
});
}, false);
这很简单,可靠,并且不需要像操作心跳那样的服务器智能。
当然,就像webdev中的任何好东西一样,IE compat缺乏......