jQuery ajax泛型错误处理,并根据具体情况而定

时间:2011-02-03 14:22:47

标签: jquery ajax error-handling

我有一个通用的ajax错误处理程序,如下所示:

$('html').ajaxError(function(e, xhr, settings, exception) {

    var message = '';

    if (xhr.status == 0) {
        message = 'You are offline!\n Please check your network.';
    }
    else if (xhr.status == 403) {
        window.location.href = $('#logon').attr('href');
    }
    else if (xhr.status == 404) {
        message = 'Requested URL not found.';
    }
    else if (xhr.status == 500) {

        message = xhr.responseText;

        $('#cboxLoadedContent div.news_article_content').append('<p>' + message + '</p>');

        try {//Error handling for POST calls
            message = JSON.parse(xhr.responseText);
        }

        catch (ex) {//Error handling for GET calls
            message = xhr.responseText;
        }

    }
    else if (errStatus == 'parsererror') {
        message = 'Error.\nParsing JSON Request failed.';

    }
    else if (errStatus == 'timeout') {
        message = 'Request timed out.\nPlease try later';
    }
    else {
        message = ('Unknown Error.\n' + xhr.responseText);
    }

    if (message != '' && xhr.status != 500) {
        message = message;
    }

    if (xhr.status != 403) {

        $('#icis_dashboard').append('<p id="ajax_error_msg" class="offScreen">' + message + '</p>');

        errorBox({
            inline: true,
            width: 0,
            href: '#ajax_error_msg',
            onLoadCall: function() { $('#cboxLoadedContent').jScrollPaneRemove(); },
            onCleanupCall: function() { $('#ajax_error_msg').remove(); }
        });
    }

});

因此,当错误不是403时,会显示一个对话框,其中包含与错误相关的文本。

这很好,但我想做的是将通用处理程序作为备份,然后在原始ajax调用中单独处理每个错误。

因为备份处理程序警告404上的“bar”我想警告“foo”:

            error: function(xhr) {
            if (xhr.status == 404) {
                //window.location.href = $('#logon').attr('href');
                alert("foo");    
            }
        }

无论如何我都坚持这样做?我不知道如何防止备份被触发,因为它们现在似乎都在触发。

7 个答案:

答案 0 :(得分:20)

您可以在执行自己的错误处理的ajax函数中将ajax属性“global”设置为false。这应该可以防止全局错误处理。检查:http://api.jquery.com/jQuery.ajax#toptions

答案 1 :(得分:8)

我认为你不能用jQuery来控制它。在ajax调用期间发生的任何错误都会调用全局ajaxError。但是,在全局回调之前调用“本地”错误回调,因此您可以设置一个变量来告诉全局回调不要运行。

例如:

var handledLocally = false;

$('html').ajaxError(function(e, xhr, settings, exception) {
    if (!handledLocally){
        //run the normal error callback code and the reset handledLocally
    }
});

error: function(){
    //set handledLocally to true to let the global callback it has been taken care of
    handledLocally = true;
}

您可以查看此jsFiddle,其中显示了如何完成此操作(请务必在点击链接之前单击顶部的运行):http://jsfiddle.net/e7By8/

答案 2 :(得分:4)

我认为设置全局变量是个坏主意,因为你可以同时拥有多个ajax请求。如上所述&#34;本地&#34;在全局回调之前调用错误回调。我的解决方案只是将一些自定义属性附加到jqXHR对象,例如 processedLocally ,并在本地处理程序中将其设置为true并在全局处理程序中检查它。

本地处理:

$.ajax({
   //some settings
   error:function(jqXHR, textStatus, errorThrown){
      //handle and after set
      jqXHR.handledLocally = true

   }
})

全球处理:

$(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {
    if (jqXHR.handledLocally)) {
        return;
    }
    //handle global error
})

答案 3 :(得分:3)

我们实际上通过以下方式解决了这个问题:

function ajaxError(xhr, textStatus, errorThrown) {

    var message = '';

    if (xhr.status == 0) {
        message = 'You are offline!\n Please check your network.';
    }
    else if (xhr.status == 403) {
        window.location.href = $('#logon').attr('href');
    }
    else if (xhr.status == 404) {
        message = 'Requested URL not found.';
    }
    else if (xhr.status == 500) {

        message = xhr.responseText;

        $('#cboxLoadedContent div.news_article_content').append('<p>' + message + '</p>');

        try {//Error handling for POST calls
            message = JSON.parse(xhr.responseText);
        }

        catch (ex) {//Error handling for GET calls
            message = xhr.responseText;
        }

    }
    else if (errStatus == 'parsererror') {
        message = 'Error.\nParsing JSON Request failed.';

    }
    else if (errStatus == 'timeout') {
        message = 'Request timed out.\nPlease try later';
    }
    else {
        message = ('Unknown Error.\n' + xhr.responseText);
    }

    if (message != '' && xhr.status != 500) {
        message = message;
    }

    if (xhr.status != 403) {

        $('#icis_dashboard').append('<p id="ajax_error_msg" class="offScreen">' + message + '</p>');

        errorBox({
            inline: true,
            width: 0,
            href: '#ajax_error_msg',
            onLoadCall: function() { $('#cboxLoadedContent').jScrollPaneRemove(); },
            onCleanupCall: function() { $('#ajax_error_msg').remove(); }
        });
    } 
};

因此,现在每个AJAX调用都会以两种方式之一引用该函数:

1)如果我们想要默认发生

error: ajaxError

2)如果我们想要针对特定​​情况,如果没有捕获,则继续使用默认

    error: function(xhr) {

        if (xhr.status == 404) {
            alert("local");
        }
        else {
            // revert to default
            ajaxError.apply(this, arguments);
        }
    }

答案 4 :(得分:3)

这是一个老问题,但这可能对某人有用。 this answer的问题在于您可能需要执行全局处理程序中的代码。我发现this other answer更有用,但使用全局变量并不是一个很好的做法。此外,您可能同时有多个ajax调用,但它无法正常工作。我建议这个替代方案略有不同:

$(document).ajaxError(function(event, jqxhr, settings, thrownError) {
    // Global validation like this one:
    if (jqxhr.status == 401) { window.location = "/login"; }

    if (!settings.handErrorLocally) {
        // Unhandled error.
        alert("Ooops... we have no idea what just happened");
    }
});

然后在调用任何ajax时你可能会自己处理错误:

$.ajax({
    url: "/somePage/",
    handErrorLocally: true
}).done(function () {
    alert("good");
}).fail(function () {
    alert("fail");
});

或者让全球经纪人照顾:

$.ajax({
    url: "/somePage/"
}).done(function () {
    alert("good");
});

答案 5 :(得分:2)

将全局错误处理程序定义为函数

function ajaxError() {
  var message = '';

  if (xhr.status == 0) {
    message = 'You are offline!\n Please check your network.';
  }
  .....
}

创建jQuery.ajax包装器:

function doAjax(url, fnError) {
  jQuery.ajax(url, {
    error: fnError || defaultErrorHandler 
  })
}

现在使用这个包装器而不是默认的jQuery.ajax:

doAjax('/someResource'); // defaultErrorHandler using for handle error
doAjax('/someResource', function() {...}); // custom error function using

答案 6 :(得分:1)

我正在补充Tim Banks的答案,这非常有用。我只想改变他使用全局变量并在ajax调用中使用设置的事实。我已经默认退回了,但这很容易改变。

$('html').ajaxError(function(e, xhr, settings, exception) {
    if (xhr.status == 404) {
        alert("html error callback");    
    }
});

$.ajax({
    url: "missing.html",
    global: true
});

我编辑了我的答案,使用全局设置决定是否传播到全局事件处理程序