Javascript:等到ajax请求完成关闭页面[重复]
Posted
技术标签:
【中文标题】Javascript:等到ajax请求完成关闭页面[重复]【英文标题】:Javascript: wait until ajax request finishes to close page [duplicate] 【发布时间】:2011-02-27 14:03:16 【问题描述】:我希望浏览器在发送 ajax 请求之前保持页面打开。这就是我想象中的样子
var requestsPending = 0;
window.onbeforeunload = function()
showPleaseWaitMessage();
while(requestsPending > 0);
// called before making ajax request, atomic somehow
function ajaxStarted()
requestsPending++;
// called when ajax finishes, also atomic
function ajaxFinished()
requestsPending--;
不幸的是,JS 不做多线程。据我了解,回调 (ajaxFinished) 永远不会执行,因为浏览器会尝试等待 while 循环完成执行它,因此它将永远循环。
这样做的正确方法是什么?有没有办法强制 JS 评估其待办事项列表中的下一件事,然后返回到 while 循环?或者一些语法来“加入”一个ajax调用?我正在为我的 ajax 使用 DWR。
谢谢, -最大
【问题讨论】:
【参考方案1】:编辑根据您在下面的评论,修改后的答案:
如果你想阻塞直到一个先前发起的请求完成,你可以这样做:
window.onbeforeunload = function(event)
var s;
event = event || window.event;
if (requestsPending > 0)
s = "Your most recent changes are still being saved. " +
"If you close the window now, they may not be saved.";
event.returnValue = s;
return s;
然后,浏览器会提示用户询问他们是要离开页面还是留在页面上,让他们自行控制。如果他们停留在页面上并且在提示出现时请求已经完成,那么下次他们关闭页面时,它会让他们在不询问的情况下关闭它。
请注意,在现代浏览器上,您的消息将不会显示;相反,浏览器将使用通用消息。所以在现代浏览器上,返回任何非空白字符串就足够了。不过,您可能希望返回一个有用的字符串(例如上面的),以防您的用户使用仍然会显示它的过时浏览器。
更多关于询问用户是否取消关闭事件here和here。
旧答案:
理想情况下,如果可能,您希望避免这样做。 :-)
如果无法避免,可以进行 Ajax 请求同步,这样它就会阻塞onbeforeunload
进程,直到它完成。我不知道 DWR,但我希望它有一个标志来控制请求是否同步。在原始 XmlHTTPRequest API 中,这是open
的第三个参数:
req.open('GET', 'http://www.mozilla.org/', false);
^ false = synchronous
大多数libraries 都会有一个等价物。例如,在Prototype 中,它是选项中的asynchronous: false
标志。
但同样,如果您可以避免在页面卸载过程中触发 Ajax 请求,我会的。在设置、传输和完成请求时会有明显的延迟。最好让服务器使用超时来关闭您尝试关闭的任何内容。 (这可能是一个相当短的超时时间;您可以通过在页面打开时定期在页面中使用 异步 Ajax 请求来保持会话处于活动状态 - 例如,每分钟一个,两分钟后超时。)
【讨论】:
即使你让它同步,浏览器也不会等待,至少不是所有的......所以它仍然不可靠(它应该是 IMO,我的浏览器不应挂起,因为 10 个选项卡中有 1 个想要发出一些我不关心的 AJAX 请求)。 @Nick:你说的是beforeunload
,还是unload
?因为在beforeunload
中,如果我愿意,我可以启动像alerts
这样具有侵入性的东西。我有一段时间没有这样做(在beforeunload
期间发送请求)(因为我认为这不是一个好主意),但是当我几年前这样做时,它在(我认为)IE6 中可靠地工作、IE7 和 Firefox ......嗯......无论 Firefox 几年前是最新的。 :-)
@T.J.警报阻止了 UI 线程,它不是像 ajax 那样的回调,所以不同的球赛......像 OP 试图做的事情在任何一种情况下都不起作用(大多数时候),这是一场火灾并忘记......但即使是火部分是否完成取决于浏览器。
诀窍是,这些 ajax 调用是在用户关闭窗口之前启动的。例如,假设您有一个附有编辑链接的可重新排序的元素列表。如果用户重新排序列表,然后在 ajax 告诉服务器列表已重新排序之前单击链接,当浏览器转到编辑页面时,他会丢失更改。我想强制浏览器等到ajax调用完成后再离开页面。
@Nick:我得再试一次(现在不能)。但根据 OP 的评论,事实证明,这不是他想做的事! :-)【参考方案2】:
简而言之,您不能(也不应该)这样做。如果用户关闭浏览器,它就会关闭...没有unload
样式事件保证完成,而涉及延迟的 AJAX 操作更多不太可能完成。
您应该考虑在另一个时间点触发您的事件,或者完全改变方法,但是在 unload
事件中进行 AJAX 调用将是不可靠的,充其量。
作为对上述不应该部分的补充,请这样想,在任何给定窗口上通常打开多少个选项卡?我通常打开 4-6 个 chrome 窗口,每个窗口有 5-12 个选项卡...我的浏览器窗口是否应该挂起,因为其中 1 个选项卡想要发出一些我不关心的 AJAX 请求?我不希望它作为一个用户,所以我不会尝试作为一个开发者来做它。这当然只是一个观点,但值得深思。
【讨论】:
那么什么是解决这个问题的好方法呢?例如,假设您有一个附加了编辑链接的可重新排序的元素列表。如果用户重新排序列表,然后在 ajax 告诉服务器列表已重新排序之前单击链接,当浏览器转到编辑页面时,他会丢失更改。 @maxdj - 一个.live()
处理程序,例如,如果 ajax 请求正在进行,则返回 false,如果不是,则继续......任何阻止链接在不应该工作时工作的东西真的。以上是关于Javascript:等到ajax请求完成关闭页面[重复]的主要内容,如果未能解决你的问题,请参考以下文章