Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript:等待ajax请求完成后关闭页面_Javascript_Ajax_Dwr - Fatal编程技术网

Javascript:等待ajax请求完成后关闭页面

Javascript:等待ajax请求完成后关闭页面,javascript,ajax,dwr,Javascript,Ajax,Dwr,我希望浏览器在发送ajax请求之前保持页面打开。这就是我想象中的样子 var requestsPending = 0; window.onbeforeunload = function() { showPleaseWaitMessage(); while(requestsPending > 0); } // called before making ajax request, atomic somehow function ajaxStarted() { req

我希望浏览器在发送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调用?我将DWR用于我的ajax

谢谢, -Max

简而言之,您不能(也不应该)这样做。如果用户关闭浏览器,它就关闭了……没有
unload
样式的事件保证会完成,而使用AJAX处理延迟的事情不太可能完成

您应该考虑在另一点触发事件,或者完全改变方法,但是在
unload
事件中进行AJAX调用最多是不可靠的


作为上述“不应该”部分的补充,请这样想,在任何给定窗口上,您通常打开多少个选项卡?我通常会打开4-6个chrome窗口,每个窗口有5-12个选项卡…我的浏览器窗口是否应该保持打开状态,因为其中一个选项卡想要发出一些我不关心的AJAX请求?我不希望它以用户的身份出现,所以我不会以开发人员的身份尝试这样做。这当然只是一个观点,但值得思考。

根据您的以下评论,编辑一个修改后的答案:

如果要阻止,直到先前启动的请求完成,可以这样做:

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;
    }
}
然后,浏览器将提示用户询问他们是想离开页面还是留在页面上,并让他们控制页面。如果他们停留在页面上,并且在提示出现时请求已完成,那么下次他们去关闭页面时,将允许他们不经请求就关闭页面

请注意,在现代浏览器上,您的消息不会显示;相反,浏览器将使用通用消息。因此,在现代浏览器上,返回任何非空字符串就足够了。尽管如此,如果用户使用的是过时的浏览器仍然会显示它,您可能希望返回一个有用的字符串(如上面所述)

有关询问用户是否取消关闭事件和的详细信息


旧答案

理想情况下,如果可能,您希望避免这样做。:-)

如果无法避免,则可以使Ajax请求同步,以便它在完成之前阻止
onbeforeunload
过程。我不知道DWR,但我希望它有一个标志来控制请求是否同步。在原始XMLHttpRequestAPI中,这是打开的第三个参数:

req.open('GET', 'http://www.mozilla.org/', false);
                                            ^ false = synchronous
大多数将有一个同等的。例如,在中,是选项中的
asynchronous:false
标志


但是,如果您可以避免在页面卸载过程中触发Ajax请求,我会这样做。在设置、传输和完成请求时,会有明显的延迟。最好让服务器使用一个超时来关闭您试图关闭的任何东西。(这可能是一个相当短的超时时间;您可以在页面打开时定期在页面中使用异步Ajax请求来保持会话的活动状态,例如,一分钟一个,两分钟后超时。)

即使您使其同步,浏览器也不会等待,至少不是所有请求……因此仍然不可靠(应该是IMO,我的浏览器不应该挂起,因为10个选项卡中有1个想要发出一些我不关心的AJAX请求)。@Nick:你是说
卸载前
,还是
卸载前
?因为在
卸载前
中,如果我愿意,我可以启动像
警报
这样的侵入性东西。我没有这样做(在卸载之前的
期间发送请求)在一段时间内(因为我认为这不是一个好主意),但当我在几年前这样做时,它在(我认为)IE6、IE7和Firefox中可靠地工作……嗯……无论几年前Firefox是什么@T.J.警报会阻止UI线程,它不像ajax那样是回调,所以不同的游戏……像OPs这样的尝试在这两种情况下都不会起作用(大多数情况下),这是一个fire-and-forget…但即使是fire部分是否完成也取决于浏览器。诀窍是,这些ajax调用是在用户关闭窗口之前启动的。例如,假设您有一个可重新排序的元素列表,其中附加了编辑链接。如果用户重新排序该列表,则在ajax告诉服务器t之前单击该链接列表已重新排序,当浏览器转到编辑页时,他丢失了更改。我想强制浏览器等到ajax调用完成后再离开该页。@Nick:我必须再试一次(现在不行)。但根据OP的评论,这不是他想做的事!:-)那么,解决这个问题的好办法是什么呢?例如,假设您有一个附加了编辑链接的可重排序元素列表。如果用户对列表重新排序,然后在ajax通知服务器列表已重新排序之前单击链接,则当浏览器转到编辑页时,用户将丢失所做的更改。@maxdj-A
.live()
处理程序,例如,如果ajax请求正在进行,则返回false,如果它不是…任何阻止链接正常工作的东西,则继续。