Chrome 中的 window.onbeforeunload ajax 请求
Posted
技术标签:
【中文标题】Chrome 中的 window.onbeforeunload ajax 请求【英文标题】:window.onbeforeunload ajax request in Chrome 【发布时间】:2011-06-24 04:11:01 【问题描述】:我有一个通过 Ajax 处理机器远程控制的网页。当用户离开页面时,我想自动断开与机器的连接。所以这里是代码:
window.onbeforeunload = function ()
bas_disconnect_only();
断开连接函数只是向 php 服务器端脚本发送一个 HTTP GET 请求,该脚本执行断开连接的实际工作:
function bas_disconnect_only ()
var xhr = bas_send_request("req=10", function ()
);
这在 FireFox 中运行良好。但是对于 Chrome,根本不会发送 ajax 请求。有一个不可接受的解决方法:向回调函数添加警报:
function bas_disconnect_only ()
var xhr = bas_send_request("req=10", function ()
alert("You're been automatically disconnected.");
);
添加警报调用后,请求将成功发送。但正如您所看到的,这根本不是一个真正的解决方法。
谁能告诉我这是否可以通过 Chrome 实现?我正在做的事情在我看来完全合法。
谢谢,
【问题讨论】:
“bas_send_request”函数在哪里? Pointy:bas_send_request() 是一个简单的包装器,它创建一个 ajax 请求并发送它。我认为没有必要展示那种细节。 【参考方案1】:这与较新版本的 Chrome 相关。
与@Garry English said 一样,在页面onunload
期间发送async
请求将不起作用,因为浏览器会在发送请求之前终止线程。不过发送sync
请求应该可以。
这在 Chrome 29 之前是正确的,但在 Chrome V 30 上它突然停止工作as stated here。
目前看来,这样做的唯一方法是使用onbeforeunload
事件as suggested here。
但请注意:其他浏览器根本不允许您在 onbeforeunload 事件中发送 Ajax 请求。所以你要做的就是在卸载和卸载前都执行这个动作,并检查它是否已经发生了。
类似这样的:
var _wasPageCleanedUp = false;
function pageCleanup()
if (!_wasPageCleanedUp)
$.ajax(
type: 'GET',
async: false,
url: 'SomeUrl.com/PageCleanup?id=123',
success: function ()
_wasPageCleanedUp = true;
);
$(window).on('beforeunload', function ()
//this will work only for Chrome
pageCleanup();
);
$(window).on("unload", function ()
//this will work for other browsers
pageCleanup();
);
【讨论】:
@Sebas,如果您可以提供更多详细信息,也许我们可以尝试提供帮助。究竟是什么失败了?它被称为 ata all 吗?你确定你的请求是同步的吗? @Mohoch,它突然停止工作。我怀疑新版本的 chrome 会造成问题,但在我意识到更多测试之前我无法确定。我正在使用一个框架,有一个布尔值可以将 ajax 调用设置为同步,并且它在整个软件中运行良好,除了窗口的 onbeforeunload 事件。 (引发网络错误) @AitazazKhan,答案本身有一个示例,同时使用 onunload 和 onbeforeunload。您还可以查看this page 以获得更多解释和示例。如果我在您的问题中遗漏了什么,请随时详细说明,以便我查明确切的问题。 太棒了。你可以直接写 ... .on('unload beforeunload', ... 直接把函数打包进去,不是吗? chrome 80 及更高版本不支持此功能。我刚刚遇到一个问题并降落在这里。 developers.google.com/web/updates/2019/12/chrome-80-deps-rems【参考方案2】:我遇到了同样的问题,Chrome 没有在 window.unload 事件中向服务器发送 AJAX 请求。
如果请求是同步的,我只能让它工作。我可以使用 Jquery 来做到这一点,并将 async 属性设置为 false:
$(window).unload(function ()
$.ajax(
type: 'GET',
async: false,
url: 'SomeUrl.com?id=123'
);
);
以上代码在 IE9、Chrome 19.0.1084.52 m 和 Firefox 12 中适用于我。
【讨论】:
请阅读下面@Mohoch 给出的更新答案。它提供了反映浏览器更改的更新答案。 请注意,不推荐同步 ajax 调用。 IIRC,现代浏览器在执行同步 ajax 时会在控制台中显示警告。 解决方案无效。它只偶尔工作一次。async: false
自 jQuery 1.8 (api.jquery.com/jQuery.ajax) 以来已被弃用。
同步 XHR 调用应在页面关闭期间删除。它将在 Chrome 80 中删除。chromestatus.com/feature/4664843055398912【参考方案3】:
检查为此目的而构建的Navigator.sendBeacon() 方法。
MDN 页面说:
navigator.sendBeacon() 方法可用于异步 将小型 HTTP 数据从用户代理传输到 Web 服务器。
此方法可满足分析和诊断代码的需求 通常尝试在卸载之前将数据发送到 Web 服务器 的文件。过早发送数据可能会导致错过 收集数据的机会。但是,确保数据已 在卸载文档期间发送的内容 传统上对开发人员来说很困难。
这是一个相对较新的 API,IE 似乎还不支持。
【讨论】:
请注意,一些广告拦截器(如 uBlock Origin)出于某种跟踪预防的目的而阻止 Navigator.sendBeacon。因此,您的应用根本无法依赖它。【参考方案4】:同步 XMLHttpRequest
已被弃用 (Synchronous and asynchronous requests)。因此,jQuery.ajax()
的async: false
选项也已被弃用。
在beforeunload
或unload
期间使用同步请求似乎不可能(或非常困难)
(Ajax Synchronous Request Failing in Chrome)。所以推荐使用sendBeacon
,我绝对同意!
简单地说:
window.addEventListener('beforeunload', function (event) // or 'unload'
navigator.sendBeacon(URL, JSON.stringify(...));
// more safely (optional...?)
var until = new Date().getTime() + 1000;
while (new Date().getTime() < until);
);
【讨论】:
你的意思是在窗口卸载期间同步和异步请求都被弃用了吗? @surajnaik SynchronousXMLHttpRequest
一般,我猜。【参考方案5】:
尝试创建一个变量(最好是布尔变量)并在您从 Ajax 调用获得响应后对其进行更改。并将bas_disconnect_only()
函数放在一个while 循环中。
我曾经也遇到过这样的问题。我认为这是因为 Chrome 不等待 Ajax 调用。我不知道我是如何修复它的,我还没有尝试过这段代码,所以我不知道它是否有效。这是一个例子:
var has_disconnected = false;
window.onbeforeunload = function ()
while (!has_disconnected)
bas_disconnect_only();
// This doesn't have to be here but it doesn't hurt to add it:
return true;
而在bas_send_request()
函数内部(xmlhttp是HTTP请求):
xmlhttp.onreadystatechange = function()
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
has_disconnected = true;
祝你好运,我希望这会有所帮助。
【讨论】:
感谢您的回复。这看起来值得一试。但是我设法找到了另一个不需要客户端断开连接的解决方案。还是谢谢你。【参考方案6】:当用户离开页面并向后端发送 ajax 请求时,我必须跟踪任何情况。
var onLeavePage = function()
$.ajax(
type: 'GET',
async: false,
data: val1: 11, val2: 22,
url: backend_url
);
;
/**
* Track user action: click url on page; close browser tab; click back/forward buttons in browser
*/
var is_mobile_or_tablet_device = some_function_to_detect();
var event_name_leave_page = (is_mobile_or_tablet_device) ? 'pagehide' : 'beforeunload';
window.addEventListener(event_name_leave_page, onLeavePage);
/**
* Track user action when browser tab leave focus: click url on page with target="_blank"; user open new tab in browser; blur browser window etc.
*/
(/*@cc_on!@*/false) ? // check for Internet Explorer
document.onfocusout = onLeavePage :
window.onblur = onLeavePage;
请注意,桌面浏览器中会触发事件“pagehide”,但当用户单击浏览器中的后退/前进按钮时它不会触发(在最新的当前版本的 Mozilla Firefox 中测试)。
【讨论】:
【参考方案7】:Try navigator.sendBeacon(...);
try
// For Chrome, FF and Edge
navigator.sendBeacon(url, JSON.stringify(data));
catch (error)
console.log(error);
//For IE
var ua = window.navigator.userAgent;
var isIEBrowser = /MSIE|Trident/.test(ua);
if (isIEBrowser)
$.ajax(
url: url,
type: 'Post',
.
.
.
);
【讨论】:
请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助、质量更好,并且更有可能吸引投票。 感谢您发布此内容!【参考方案8】:我一直在寻找一种通过 AJAX 请求检测离开页面的方法。它就像我每次使用它时一样工作,并用 mysql 检查它。这是代码(在 Google Chrome 中工作):
$(window).on("beforeunload", function ()
$.ajax(
type: 'POST',
url: 'Cierre_unload.php',
success: function ()
)
)
【讨论】:
以上是关于Chrome 中的 window.onbeforeunload ajax 请求的主要内容,如果未能解决你的问题,请参考以下文章
Chrome扩展开发之三——Chrome扩展中的数据本地存储和下载