关于javascript:JQuery Ajax – 如何在进行Ajax调用时检测网络连接错误

JQuery Ajax - How to Detect Network Connection error when making Ajax call

我有一些Javascriptjquery代码,它每隔5分钟对服务器进行一次Ajax调用,这是为了保持服务器会话的活动状态并保持用户登录。我在jquery中使用的是$.ajax()方法。这个函数似乎有一个"错误"属性,当用户的Internet连接中断时,我会尝试使用这个属性,以便keepalive脚本继续运行。我使用以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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调用时是否有检测网络连接问题的方法?


1
2
3
4
5
6
7
8
9
10
11
12
13
// 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


你应该加上:timeout: ,$.ajax({})的某个地方。另外,cache: false,在一些情况下可能会有所帮助。

.ajax有很好的文档记录,您应该检查那里的选项,可能会发现一些有用的东西。

祝你好运!


因为我不能复制这个问题,所以我只能建议在Ajax调用上尝试超时。在jquery中,您可以使用$.ajaxsetup设置它(对于所有的$.ajax调用,它都是全局的),或者您可以专门为您的调用设置它,如下所示:

1
2
3
4
5
6
7
$.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调用,但无法区分实际的网络问题和连接丢失。


在本例中,我看到的是,如果我拉动客户机的网络电缆并进行调用,就会调用Ajax成功处理程序(为什么,我不知道),并且数据参数是一个空字符串。因此,如果您考虑到真正的错误处理,您可以这样做:

1
2
3
4
5
6
7
8
9
10
11
function handleError(jqXHR, textStatus, errorThrown) {
    ...
}

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

如果要跨域调用,请使用jsonp。否则不返回错误。


使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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.');
    }

};

(下面的更多代码-上载图像示例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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();
 }
 };


以下是我在用户网络崩溃或页面更新失败时提醒用户的方法:

  • 我在页面上有一个DIV标记,我把当前时间放在这里,每10秒更新一次这个标记。它看起来像这样:22:09:10

  • 在更新DIV标记中时间的javascript函数的末尾,我把它(在用Ajax更新时间之后):

    1
    2
    3
    4
    5
    var new_value = document.getElementById('reloadthis').innerHTML;
    var new_length = new_value.length;
    if(new_length<1){
        alert("NETWORK ERROR!");
    }
  • 就是这样!当然,您可以用您想要的任何东西替换警报部分。希望这有帮助。


    你试过这个吗?

    1
    $(document).ajaxError(function(){ alert('error'); }

    那应该能处理所有的半开。我在这里找到的。在那里,您还可以将这些错误写入Firebug控制台。