jQuery的ajaxError()处理程序在页面未完成加载时用户离开页面时触发。

25
我们使用jQuery的全局ajaxError()处理程序来向用户提示任何AJAX请求失败的情况:
$(document).ajaxError(function() {  
    $("There was a network or server error. Please try again later.").dialog({  
        title: "Error",  
        modal: true,  
        resizable: false,  
        buttons: { 'Ok': function() { (this).dialog("close"); } }  
    });  
});  

不幸的是,如果用户在页面加载完成之前离开页面,这个全局错误处理程序也会触发。以下是重现错误的步骤:

  1. 用户访问包含通过 AJAX 加载的元素的页面 A。
  2. 页面 A 上的 AJAX 元素开始加载。
  3. 在页面 A 上的 AJAX 元素加载完成之前,用户点击链接以访问页面 B。
  4. 错误对话框出现后很快就会消失,然后浏览器将重定向到页面 B。

有什么想法可以让 ajaxError() 不能因为用户访问新页面而触发错误?

更新:在评论中加入建议后,这是我的代码:

// I added a 3 second delay to our error dialog, enough time
// for the user to leave for a new page:
$(document).ajaxError(function() {
    setTimeout(my_error_handler, 3000);
});

// Warn user before leaving page if AJAX is still loading.
// Not sure I'll keep this:
$(document).ajaxStart(function() {
    ajaxing = true;
});

$(document).ajaxStop(function() {
    ajaxing = false;
});

window.onbeforeunload = function() {
    if (typeof(ajaxing) != 'undefined' && ajaxing) {
        return "Page elements are still loading!";
    }
};
2个回答

16

是的,如果用户导航到另一页,xhr将会中止,这实际上是一次不成功的通讯。解决方法是注册一个onbeforeunload事件的侦听器,并在那里取消绑定ajaxError,基本上意味着:用户即将离开页面,所以我不希望被告知可能会发生的ajax错误。

有些网站,如Gmail,则相反:如果您试图在某些ajax请求仍在进行时导航离开页面,它会弹出提示,指出您仍有一些进程正在运行,并让用户决定是否继续留在该网站直到请求完成,还是继续导航离开。


2
GMail的方法要好得多! - TheVillageIdiot
2
好的,如果你必须采用通用的万能方法,我想我也更喜欢这种方式。不过,如果在调用ajax时传递一个标志来确定当前请求是否关键,那我会更喜欢。例如,如果请求只是为了保持会话活动或检查新消息之类的事情,你可能希望让它静默地中止。 - David Hedlund
David,谢谢你的建议。我还没有测试哪些浏览器支持onbeforeunload,但它在FF 3.5上运行良好。我还添加了一个3秒钟的延迟到错误对话框(这是之前评论中的一个建议,现在似乎已经被删除了)。 - richardkmiller
2
有时候onbeforeunload事件会在ajaxError事件之后触发。例如在Chrome浏览器中,当一个请求正在等待时点击返回按钮,会先报错,然后才会触发window.onbeforeunload事件。 - Ross
如何知道页面导航时是否仍有一些Ajax请求未完成?定义一个全局变量来记住它吗?还有更好的方法吗? - hiway

10

根据David Hedlund的回答,这是适用于我的代码:

//enable global ajax error handling
$(document).ajaxError(function (event, request, settings) {
    //your error handling code here
});

//user leaving page so ignore any unfinished ajax loads
$(window).bind('beforeunload', function () {
    $(document).unbind('ajaxError');
});

我从jQuery的ajaxError文档的评论部分获得了关于'ajaxError'规范的信息。为了支持Chrome(IE与document的绑定正常),我必须将beforeunload绑定到$(window)上。由于当我将其绑定到$(window)时,.ajaxError不会触发,所以我采用了这种window/document的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接