封装jQuery的$.ajax()方法以定义全局错误处理

29

从像这样的问题开始,我想要包装jQuery的$.ajax()方法,以便我可以在一个地方提供错误处理,在整个应用程序的远程调用中自动使用它。

简单的方法是创建一个新名称,类似于$.get()和$.post()将外观实现为$.ajax()。但是,我希望重用名称$.ajax(),这样我们可以让我们的其余代码使用标准的jQuery语法,隐藏我们已经添加了自己的错误处理的事实。这样做实际可行和/或好吗?或者可能是一个可怕的主意?

编辑:到目前为止的回复表明.ajaxError()是正确的方法。我知道这会捕获400和500级别的错误,但是否有办法(通过此事件处理程序或其他方式)也捕获302重定向?我正在尝试处理重定向到登录页面的响应,但当它是XHR请求时,我们希望拦截该重定向,以允许用户取消操作,而不是强制将他们自动转发。


顺便提一下,对于非登录的AJAX请求的响应,应该返回401而不是302。无论如何,这是值得思考的问题。 - gtd
5个回答

36

您可能需要查看$.ajaxError

$(document).ajaxError(function myErrorHandler(event, xhr, ajaxOptions, thrownError) {
  alert("There was an ajax error!");
});

jQuery提供了许多其他附加全局处理程序的方法

回答您的编辑问题,您可以使用$.ajaxSuccess捕获成功的ajax请求,您也可以使用$.ajaxComplete捕获所有(成功和失败的)请求。您可以从xhr参数中获取响应代码,例如:

$(document).ajaxComplete(function myErrorHandler(event, xhr, ajaxOptions, thrownError) {
  alert("Ajax request completed with response code " + xhr.status);
});

@Marc L:已根据您提供的额外信息进行了编辑。此外,您可能会发现这很有趣:https://dev59.com/AnVC5IYBdhLWcg3wvT1a - sje397
3
尝试使用 $(document).ajaxError(…); - 使用 $.ajaxError(...) 对我无效。 - ripper234
这个解决方案不能捕获302/重定向 :( - 除此之外是一个很好的解决方案! - OverMars

3

jQuery有一个非常方便的方法叫做 $.ajaxSetup(),它允许你设置适用于所有基于jQuery的AJAX请求的选项。通过将此方法放置在主文档准备好的函数中,所有的设置都将自动应用于其余的函数,并且只需在一个位置进行设置。

$(function () {
    //setup ajax error handling
    $.ajaxSetup({
        error: function (x, status, error) {
            if (x.status == 403) {
                alert("Sorry, your session has expired. Please login again to continue");
                window.location.href ="/Account/Login";
            }
            else {
                alert("An error occurred: " + status + "nError: " + error);
            }
        }
    });
});

参考: https://cypressnorth.com/programming/global-ajax-error-handling-with-jquery/

这篇文章介绍了如何使用jQuery来全局处理Ajax请求的错误。通过监听ajaxError事件,我们可以在发生错误时执行自定义的回调函数。此外,在回调函数中,我们还可以根据不同的错误类型进行相应的处理。

我认为这比ajaxError()更好,因为没有必要将监听器绑定到DOM上,并且当你说全局时更有意义。 - Wancieho
1
@Wancieho 请注意:全局回调函数应该使用它们各自的全局Ajax事件处理程序方法——.ajaxStart()、.ajaxStop()、.ajaxComplete()、.ajaxError()、.ajaxSuccess()、.ajaxSend()来设置,而不是在$.ajaxSetup()的选项对象中设置。参考链接 另外,从jQuery 1.9开始,所有jQuery全局Ajax事件的处理程序(包括使用.ajaxError()方法添加的处理程序)都必须附加到document上。参考链接 - Mavelo
抱歉格式不美观,评论中只能做到这么多。 - Mavelo

2
实际上,jQuery提供了一个钩子,就是.ajaxError(),专门用于此目的。所有通过$ajaxError()绑定的处理程序都将在页面完成具有错误的ajax请求时被调用。指定选择器允许您在.ajaxError()处理程序内引用this
要将其用于处理页面上所有ajax请求的错误并使用this指向document,您可以像这样操作:
$(document).ajaxError(function(event, request, settings){
   alert("Error requesting page: " + settings.url);
});

澄清一下,ajaxError 处理所有的 ajax 失败,而不仅仅是与选择器匹配的失败。使用选择器只允许您在回调函数中使用“this”关键字来引用该元素。 - David Tang

1
有时,在调用本地错误处理函数之前,您可能希望进行全局错误处理。
像这个例子中使用$.ajaxPrefilter是我使用的最佳解决方案。
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    let error = options.error;
    options.error = function (jqXHR, textStatus, errorThrown) {
        // global error handling first
        console.log('global ajax error');
        
        // override local error handling if exists
        if ($.isFunction(error)) {
            return $.proxy(error, this)(jqXHR, textStatus, errorThrown);
        }
    };
});

0

我认为这是个不好的主意。把$.ajax进行包装是可以的,但是您正在谈论重新定义它。任何没有意识到这一点的人都会得到意想不到的结果。

正如其他人所提到的,绑定一个处理程序到$.ajaxError是正确的方法。


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