当用户单击刷新时处理 ajax 错误

Posted

技术标签:

【中文标题】当用户单击刷新时处理 ajax 错误【英文标题】:handle ajax error when a user clicks refresh 【发布时间】:2010-10-16 13:01:47 【问题描述】:

如果这是我应该能够查找的内容,我深表歉意。我想要的所有术语都超载了..

这是我的问题:当我打开一个页面时,它会触发一系列的 ajax 调用。如果我然后按 Shift+Refresh,所有这些 ajax 调用都被视为错误,并在整个页面本身重新加载之前显示它们的错误消息对话框。

所以错误是由客户端触发的 - 无论如何我可以找出是否是这种情况以便我可以忽略它?例如在 xmlhttprequest 或 ajax 函数中(我正在使用 jquery btw)

【问题讨论】:

您将代码放在 jQuery onLoad 匿名函数中,对吗?就像,在代码的开头你有: $(function() /* 在这里做所有的 ajax 调用 */ );在进行 ajax 调用之前,您应该等到 DOM 加载完毕。 【参考方案1】:

有几种建议的方法来检测这个:

一些建议使用beforeunload 处理程序来设置布尔标志,以便错误处理程序可以知道页面正在被卸载(请参阅下面的相关/重复帖子列表)。这很棒,除了mobile Safari on ios doesn't support the beforeunload event。

Sachindra suggested 一种方法不是立即触发错误函数,而是在setTimeout(..., 1000) 中延迟一秒钟。这样,当错误处理程序被调用时,页面很有可能实际上已经消失了。 “好机会”就是这样。我敢打赌,如果我有一个巨大的页面,例如许多<input>s,卸载可能需要超过1秒,然后错误处理程序可能会触发。

因此,我建议结合使用 reliably detecting beforeunload support,如果不支持 beforeunload咳嗽 iPad/iPhone 咳嗽),则恢复为 Sachindra 的延迟技巧。

查看带有beforeunload 检测的完整解决方案以及此jsfiddle 中的所有内容。

看起来情况是a little better for jQuery 2.x than for 1.x,但2.x也似乎有点不稳定,所以我觉得这个建议还是谨慎的。

P.S:还有一些建议涉及测试 XHR / jqXHR 对象中的某些字段。 (Here 和 here)。在长时间运行的 AJAX 调用期间,我没有遇到可以区分用户导航和重新启动网络服务器的组合,因此我发现这种方法对我没有用。

这也是对这些相关/重复的 Stack Overflow 问题的回答:

jQuery AJAX fires error callback on window unload? $.ajax calls success handler when request fails because of browser reloading How best to handle errors during jquery ajax calls caused by user clicking on links Detecting that a jQuery.ajax call failed because the page is reloading?

以及 Stack Overflow 之外的这些帖子:

What's the proper way to deal with AJAX error because of page reload? How to Distinguish a User-Aborted AJAX Call from an Error | I like stuff.

【讨论】:

2017 年 4 月,这个问题现在只出现在支持 beforeunload 的 Firefox 中。【参考方案2】:

[这是对上一个答案的修改,我已经解决了一些悬而未决的问题]

当用户通过刷新、单击链接或更改浏览器中的 URL 离开页面时,jQuery 会引发错误事件。您可以通过为 ajax 调用实现错误处理程序并检查 xmlHttpRequest 对象来检测这些类型的错误:

$.ajax(
    /* ajax options omitted */
    error: function (xmlHttpRequest, textStatus, errorThrown) 
         if(xmlHttpRequest.readyState == 0 || xmlHttpRequest.status == 0) 
              return;  // it's not really an error
         else
              // Do normal error handling
);

【讨论】:

这似乎不像宣传的那样工作。当我在长时间轮询期间通过禁用网络连接来引入“真正的错误”时,我还会看到 readyState == 0 和 status == 0。 这不起作用。这种方法也停止检测真正的错误 在长轮询过程中重新启动 Web 服务器也会产生 readyState == 0 && status == 0。这种方法不可靠。 它在 Firefox 中不起作用。我得到 404 错误代码并且 readyState 的值为 4【参考方案3】:
var isPageBeingRefreshed = false;

window.onbeforeunload = function() 
    isPageBeingRefreshed = true;
;

$.ajax(
    error: function (xhr, type, errorThrown) 
        if (!xhr.getAllResponseHeaders()) 
            xhr.abort();
            if (isPageBeingRefreshed) 
                return; // not an error
            
        
    
);

【讨论】:

几乎对我有用。它适用于 Firefox、Chrome、IE8、IE10 和 android 的原生浏览器。 But not in iOS's Safari。一个改进建议(在 Safari/iOS 中仍然不起作用)是使用$(window).on('beforeunload', function () ...) 而不是window.beforeunload = function () ...,以免劫持/占用 beforeunload 处理程序。仍在寻找同样适用于 iOS Safari 的东西。【参考方案4】:

上述技术不适用于周期性刷新的页面(例如每半秒)。我发现可以通过将错误处理过程延迟一小段时间来避免刷新页面引起的错误。

例子:

$.ajax(...)
.success(...)
.error(function(jqXHR) 
setTimeout(function() 
  // error showing process
, 1000);
);

除此之外

window.onbeforeunload = function() //停止 ajax 调用

事件可用于不太频繁地刷新 ajax 调用。

【讨论】:

【参考方案5】:

nisanth074Peter V. Mørch 答案的组合版本,对我有用。

示例:

var isPageBeingRefreshed = false;

$(window).on('beforeunload', function()

    isPageBeingRefreshed = true;
);

$.ajax(

    // Standart AJAX settings

).error(function()

    if (!isPageBeingRefreshed) 

        // Displaying error message
    
);

【讨论】:

以上是关于当用户单击刷新时处理 ajax 错误的主要内容,如果未能解决你的问题,请参考以下文章

单击XIB按钮时刷新当前视图控制器数据请求

在 ajax 错误(HTTP 状态代码 0)中区分失败(无网络)和取消请求

当数据源是一个数组时,jQuery DataTables刷新网格

当数据源是数组时,jQuery DataTables 刷新网格

AJAX

jQuery Ajax