Javascript $(window).unload 在离开网页之前等待 AJAX 调用完成
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3138498/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
$(window).unload wait for AJAX call to finish before leaving a webpage
提问by Richard Knop
Basically, once a user leaves a webpage in my application, I need to call a PHP script with AJAX, which will insert a time spent on the webpage to the database and then leave the page.
基本上,一旦用户在我的应用程序中离开网页,我需要使用 AJAX 调用 PHP 脚本,该脚本会将网页上花费的时间插入到数据库中,然后离开该页面。
It is important to wait for the AJAX request to finish because webpages in my application are not accessible to users unless they have spent a certain time on a previous page (let's say two minutes).
等待 AJAX 请求完成很重要,因为用户无法访问我的应用程序中的网页,除非他们在上一页上花费了一定时间(比如两分钟)。
Here is my jquery code:
这是我的 jquery 代码:
$(document).ready(function() {
var teid = TEID;
var startTime = new Date().getTime();
$(window).unload(function() {
var timeSpentMilliseconds = new Date().getTime() - startTime;
var t = timeSpentMilliseconds / 1000 / 60;
$.ajax({
type: 'POST',
url: '/clientarea/utils/record-time',
data: 'teid=' + teid + '&t=' + t
});
});
});
How should I change it so it will wait for the AJAX request to end before leaving the webpage?
我应该如何更改它以便它在离开网页之前等待 AJAX 请求结束?
EDIT:
编辑:
Or it might be better (easier) to just let the AJAX request be repeated every minute or so. Is that possible?
或者让 AJAX 请求每分钟左右重复一次可能会更好(更容易)。那可能吗?
采纳答案by Tatu Ulmanen
Well, you can set async: falseon your AJAX call to make the browser wait for the request to finish before doing anything else, but note that this will 'hang' the browser for the duration of the request.
好吧,您可以设置async: falseAJAX 调用,让浏览器在执行任何其他操作之前等待请求完成,但请注意,这将在请求期间“挂起”浏览器。
$.ajax({
type: 'POST',
async: false,
url: '/clientarea/utils/record-time',
data: 'teid=' + teid + '&t=' + t
});
From the manual:
从手册:
By default, all requests are sent asynchronous (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.
默认情况下,所有请求都是异步发送的(即默认设置为 true)。如果您需要同步请求,请将此选项设置为 false。跨域请求和 dataType: "jsonp" 请求不支持同步操作。请注意,同步请求可能会暂时锁定浏览器,从而在请求处于活动状态时禁用任何操作。
回答by user1319331
The best solution is to use navigator.sendBeacon. It is brand new functionality which is starting to get implemented in new releases of browsers. The function is available in browsers newer than Chrome 39 and Firefox 31. It is not supported by Internet Explorer and Safari at the time of writing. To make sure your request gets send in the browsers that don't support the new functionality yet, you can use this solution:
最好的解决方案是使用navigator.sendBeacon。这是全新的功能,开始在新版本的浏览器中实现。该功能在比 Chrome 39 和 Firefox 31 更新的浏览器中可用。在撰写本文时,Internet Explorer 和 Safari 不支持它。为了确保您的请求在不支持新功能的浏览器中发送,您可以使用以下解决方案:
var navigator.sendBeacon = navigator.sendBeacon || function (url, data) {
var client = new XMLHttpRequest();
client.open("POST", url, false); // third parameter indicates sync xhr
client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
client.send(data);
};
Hope this helps!
希望这可以帮助!
回答by Sixtease
How about setting a cookie in the unload handler? The server should see it on the subsequent requests.
如何在卸载处理程序中设置 cookie?服务器应该在后续请求中看到它。
<script>
$(window).unload(function(){document.cookie='left_on='+(new Date())})
</script>
回答by Reigel
for me, yours is not a good idea for the browser to wait before closing...
simply because what if I really want to close it?...
对我来说,你的浏览器在关闭之前等待不是一个好主意......
仅仅是因为如果我真的想关闭它怎么办?......
if a page bother a user, it's not good...
如果一个页面打扰用户,那就不好了......
my suggestion is, in the page, you wait for 2 minutes (if 2 minutes is the requirements), then send an ajax that the user has done his 2 minutes...
我的建议是,在页面中,你等待2分钟(如果2分钟是要求),然后发送一个用户已经完成了他的2分钟的ajax......
you can then check it on the server side if one has his 2 minutes or not...
然后你可以在服务器端检查它是否有他的 2 分钟...
回答by Iacopo
It is a bad idea to try and hiHyman your users' browser, since it will give them a bad feeling and send them away.
尝试劫持用户的浏览器是一个坏主意,因为这会给他们带来不好的感觉并将他们赶走。
If for some reason you want not to produce a new page until the user has spent a minimum time on the previous one, the best thing to do is to pilot server side, i.e. redirecting to the current page until the requested time has passed.
如果由于某种原因您不想在用户在前一个页面上花费最少时间之前不生成新页面,最好的做法是引导服务器端,即重定向到当前页面,直到请求的时间过去。
You don't even need to make ajax calls, just store in the session the timestamp of when the page was served, and don't show the following page until a certain amount of time has passed.
您甚至不需要进行 ajax 调用,只需在会话中存储页面服务的时间戳,并且在经过一定时间后才显示下一页。
Be sure to tell the users they have to wait for a new page to be ready, maybe with a simple javascript countdown.
一定要告诉用户他们必须等待新页面准备就绪,也许可以使用简单的 JavaScript 倒计时。
If you want the user to actually have the page active for a certain amount of time (i.e. not to switch to another tab/window waiting for the two minutes to elapse), well, I cannot propose an effective solution.
如果您希望用户在一段时间内实际让页面处于活动状态(即不切换到另一个选项卡/窗口等待两分钟过去),那么我无法提出有效的解决方案。
回答by jAndy
use onbeforeunload:
使用onbeforeunload:
$(document).ready(function(){
window.onbeforeunload = function(){
// $.ajax stuff here
return false;
}
});
This will at least bring the user a messageboxwhich asks him if he wants to close the current window/tab.
这至少会让用户 amessagebox询问他是否要关闭当前窗口/选项卡。
回答by sje397
I think it would be much better to use a polling technique as you suggest, though it will cause some load on the web server.
我认为按照您的建议使用轮询技术会好得多,尽管它会导致 Web 服务器上的一些负载。
$(document).ready(function() {
var teid = TEID;
var startTime = new Date().getTime();
var ajaxFunc = function() {
var timeSpentMilliseconds = new Date().getTime() - startTime;
var t = timeSpentMilliseconds / 1000 / 60;
$.ajax({
type: 'POST',
url: '/clientarea/utils/record-time',
data: 'teid=' + teid + '&t=' + t
});
};
setInterval(ajaxFunc, 60000);
})
You'll be glad when you can use websockets :)
当您可以使用 websockets 时,您会很高兴:)
回答by Martin Thurau
The jQuery.ajax()method has the option async. If you set it to falsethe call will block until the response comes back (or it timed out). I'm pretty shure, that calling this, will yause the browser to weit in the unload handler.
该jQuery.ajax()方法的选择async。如果您将其设置为false调用将阻塞,直到响应返回(或超时)。我很确定,调用此方法将使浏览器在卸载处理程序中生效。
Side note: You can't rely on this to work. If the browser gives the user the option to cancel the unload handlers (which some browsers do after a while of waiting), the "time spend on site" will never be updated. You could add a timer to the site, which periodically calls a script on the server and which updates the time. You won't have an accurate value, but in your case, this isn't needed.
旁注:你不能依赖这个来工作。如果浏览器为用户提供取消卸载处理程序的选项(某些浏览器在等待一段时间后会这样做),则“在站点上花费的时间”将永远不会更新。您可以向站点添加一个计时器,它会定期调用服务器上的脚本并更新时间。你不会有一个准确的值,但在你的情况下,这不是必需的。
If you only need to know if the user was X seconds on the page You could simply set a timeout in the onload handler (using setTimeout(function, ms)) which makes a call if the user has spend the needed time. So there would be no need for a unload handler.
如果您只需要知道用户是否在页面上停留了 X 秒,您可以简单地在 onload 处理程序中设置超时(使用setTimeout(function, ms)),如果用户花费了所需的时间,它会进行调用。所以不需要卸载处理程序。

