JQuery Ajax - 如何在进行 Ajax 调用时检测网络连接错误

Posted

技术标签:

【中文标题】JQuery Ajax - 如何在进行 Ajax 调用时检测网络连接错误【英文标题】:JQuery Ajax - How to Detect Network Connection error when making Ajax call 【发布时间】:2010-12-16 09:15:37 【问题描述】:

我有一些 javascript JQuery 代码每 5 分钟对服务器进行一次 Ajax 调用,这是为了保持服务器会话处于活动状态并保持用户登录。我在 JQuery 中使用$.ajax() 方法。这个函数似乎有一个“错误”属性,我试图在用户的互联网连接出现故障时使用它,以便 KeepAlive 脚本继续运行。我正在使用以下代码:

var keepAliveTimeout = 1000 * 10;

function keepSessionAlive()

    $.ajax(
    
        type: 'GET',
        url: 'http://www.mywebapp.com/keepAlive',
        success: function(data)
        
            alert('Success');

            setTimeout(function()
            
                keepSessionAlive();
            , keepAliveTimeout);
        ,
        error: function(XMLHttpRequest, textStatus, errorThrown)
        
            alert('Failure');

            setTimeout(function()
            
                keepSessionAlive();
            , keepAliveTimeout);
        
    );

当我运行它时,我会在屏幕上每隔 10 秒在一个警告框中弹出“成功”弹出窗口,这很好。然而,一旦我拔下网线,我什么也得不到,我期待错误函数被调用并看到一个“失败”警告框,但没有任何反应。

我是否正确假设“错误”功能仅适用于从服务器返回的非“200”状态代码?有没有办法在进行 Ajax 调用时检测网络连接问题?

【问题讨论】:

你是拔掉客户端的网线还是服务器的网线? 断开连接后是否继续收到“成功”提示? @Jeff - 导致问题的原因是客户端的 Internet 连接丢失。令人难以置信的是,这实际上正在发生,因为一些客户使用该应用程序的无线连接不可靠,并且不断掉线。有句谚语“永远不要低估最终用户想方设法破坏您的应用程序的能力”,这里绝对正确 :-) @qwertypants - 不,一旦互联网连接中断(例如拔下电缆),什么都不会发生。尽管进行了 $.ajax 尝试,但我可以在 Firebug 中看到它。 有没有办法设置连接尝试的超时时间? 【参考方案1】:
// start snippet
error: function(XMLHttpRequest, textStatus, errorThrown) 
        if (XMLHttpRequest.readyState == 4) 
            // HTTP error (can be checked by XMLHttpRequest.status and XMLHttpRequest.statusText)
        
        else if (XMLHttpRequest.readyState == 0) 
            // Network error (i.e. connection refused, access denied due to CORS, etc.)
        
        else 
            // something weird is happening
        
    
//end snippet

【讨论】:

这应该是公认的答案。在您提供给 $.ajax 的错误函数中,第一个参数提供了各种状态信息。即使您没有设置超时,它也会这样做。 对 ajax 表单做同样的事情:<form ... data-ajax-failure="YourMethod" ...></form> 和你的方法 function YourMethod(XMLHttpRequest) ..same code... 有关XMLHttpRequest.readyState的更多信息,请参阅ajax_xmlhttprequest_response.asp【参考方案2】:

您只需在$.ajax() 中的某处添加:timeout: <number of miliseconds>,。 此外,cache: false, 在某些情况下可能会有所帮助。

$.ajax is well documented,你应该检查那里的选项,可能会发现一些有用的东西。

祝你好运!

【讨论】:

有很多东西根本没有在 Ajax 中记录,并且不知何故被隐藏了:(【参考方案3】:

由于我无法复制该问题,我只能建议尝试使用 ajax 调用超时。在 jQuery 中,您可以使用 $.ajaxSetup 进行设置(对于您的所有 $.ajax 调用,它将是全局的),或者您可以专门为您的调用设置它,如下所示:

$.ajax(
    type: 'GET',
    url: 'http://www.mywebapp.com/keepAlive',
    timeout: 15000,
    success: function(data) ,
    error: function(XMLHttpRequest, textStatus, errorThrown) 
)

JQuery 将在您的通话中注册 15 秒超时;之后,如果没有来自服务器的 http 响应代码,jQuery 将执行错误回调,并将 textStatus 值设置为“超时”。有了这个,您至少可以停止 ajax 调用,但您将无法区分真正的网络问题和连接丢失。

【讨论】:

【参考方案4】:

我在这种情况下看到的是,如果我拉客户端机器的网线并进行调用,则调用了ajax成功处理程序(为什么,我不知道),并且data参数是一个空字符串。因此,如果您考虑到真正的错误处理,您可以执行以下操作:

function handleError(jqXHR, textStatus, errorThrown) 
    ...


jQuery.ajax(
    ...
    success: function(data, textStatus, jqXHR) 
        if (data == "") handleError(jqXHR, "clientNetworkError", "");
    ,
    error: handleError
);

【讨论】:

【参考方案5】:

如果你是跨域调用 Use Jsonp.否则不返回错误。

【讨论】:

【参考方案6】:

使用

xhr.onerror = function(e)
    if (XMLHttpRequest.readyState == 4) 
        // HTTP error (can be checked by XMLHttpRequest.status and XMLHttpRequest.statusText)
        selFoto.erroUploadFoto('Erro HTTP: '+XMLHttpRequest.statusText);
    
    else if (XMLHttpRequest.readyState == 0) 
        // Network error (i.e. connection refused, access denied due to CORS, etc.)
        selFoto.erroUploadFoto('Erro de rede:'+XMLHttpRequest.statusText);
    
    else 
        selFoto.erroUploadFoto('Erro desconhecido.');
    

;

(下面有更多代码 - 上传图片示例)

var selFoto = 
   foto: null,

   upload: function()
        LoadMod.show();

        var arquivo = document.frmServico.fileupload.files[0];
        var formData = new FormData();

        if (arquivo.type.match('image.*')) 
            formData.append('upload', arquivo, arquivo.name);

            var xhr = new XMLHttpRequest();
            xhr.open('POST', 'FotoViewServlet?acao=uploadFoto', true);
            xhr.responseType = 'blob';

            xhr.onload = function(e)
                if (this.status == 200) 
                    selFoto.foto = this.response;
                    var url = window.URL || window.webkitURL;
                    document.frmServico.fotoid.src = url.createObjectURL(this.response);
                    $('#foto-id').show();
                    $('#div_upload_foto').hide();           
                    $('#div_master_upload_foto').css('background-color','transparent');
                    $('#div_master_upload_foto').css('border','0');

                    Dados.foto = document.frmServico.fotoid;
                    LoadMod.hide();
                
                else
                    erroUploadFoto(XMLHttpRequest.statusText);
                

                if (XMLHttpRequest.readyState == 4) 
                     selFoto.erroUploadFoto('Erro HTTP: '+XMLHttpRequest.statusText);
                
                else if (XMLHttpRequest.readyState == 0) 
                     selFoto.erroUploadFoto('Erro de rede:'+XMLHttpRequest.statusText);                             
                

            ;

            xhr.onerror = function(e)
            if (XMLHttpRequest.readyState == 4) 
                // HTTP error (can be checked by XMLHttpRequest.status and XMLHttpRequest.statusText)
                selFoto.erroUploadFoto('Erro HTTP: '+XMLHttpRequest.statusText);
            
            else if (XMLHttpRequest.readyState == 0) 
                 // Network error (i.e. connection refused, access denied due to CORS, etc.)
                 selFoto.erroUploadFoto('Erro de rede:'+XMLHttpRequest.statusText);
            
            else 
                selFoto.erroUploadFoto('Erro desconhecido.');
            
        ;

        xhr.send(formData);
     
     else
        selFoto.erroUploadFoto('');                         
        MyCity.mensagens.push('Selecione uma imagem.');
        MyCity.showMensagensAlerta();
     
  , 

  erroUploadFoto : function(mensagem) 
        selFoto.foto = null;
        $('#file-upload').val('');
        LoadMod.hide();
        MyCity.mensagens.push('Erro ao atualizar a foto. '+mensagem);
        MyCity.showMensagensAlerta();
 
 ;

【讨论】:

【参考方案7】:

如果他们的网络出现故障或页面更新失败,我会提醒用户:

    我在放置当前时间的页面上有一个 div 标记,并且每 10 秒更新一次此标记。它看起来像这样:<div id="reloadthis">22:09:10</div>

    在更新 div-tag 中时间的 javascript 函数的末尾,我放了这个(在使用 AJAX 更新时间之后):

    var new_value = document.getElementById('reloadthis').innerhtml;
    var new_length = new_value.length;
    if(new_length<1)
        alert("NETWORK ERROR!");
    
    

就是这样!当然,您可以用您想要的任何内容替换警报部分。 希望这会有所帮助。

【讨论】:

【参考方案8】:

你试过了吗?

$(document).ajaxError(function() alert('error'); 

这应该处理所有的 AjaxErrors。我找到了here。 在那里,您还可以将这些错误写入您的 firebug 控制台。

【讨论】:

以上是关于JQuery Ajax - 如何在进行 Ajax 调用时检测网络连接错误的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JQuery .Ajax 进行 Pingdom 检查?

如何在使用 jquery 进行 ajax 操作后清空 TINYMCE 内容

如何在使用 jQuery 进行 ajax 请求后替换页面的整个 CSS?

如何使用jQuery和Ajax对DreamFactory进行基本身份验证

jquery如何进行多个ajax调用[重复]

当我从 ajax 发送数据时,如何在 jQuery 中使用 DataTables 对列进行排序?