jQuery ajax beforeSend 隐藏了`$.ajaxSetup` 一个,如何级联呢?

jQuery ajax beforeSend shadows the `$.ajaxSetup` one, How to cascade it?

我正在使用 django-rest-framework。

而且我必须在每次 jquery ajax 发送之前添加 X-CSRFToken header。

参考:https://docs.djangoproject.com/en/1.8/ref/csrf/#ajax

jQuery.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", Cookies.get('csrftoken'));
        }
    }
});

所以,一切都很好,直到我使用给定的 beforeSend 设置进行 ajax 调用:

jQuery.ajax({
    url: '...',
    data: { ... },
    beforeSend: function(xhr, settings) {
        // This function do shadows the ajaxSetup one.
    }
});

那么,有什么有效的方法可以在 jQuery.ajaxSetup 调用中级联 beforeSend 处理器吗?

如果在 $.ajaxSetup 中定义一个新的 beforeSend 注入,我可以级联之前 $.ajaxSetup 中定义的其他注入:

(function() {
    function csrfSafeMethod(method) {
        // these HTTP methods do not require CSRF protection
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    var originBeforeSend = jQuery.ajaxSettings.beforeSend;
    jQuery.ajaxSetup({
        beforeSend: function(xhr, settings) {
            // Call the previous beforeSend processor first.
            if(originBeforeSend && originBeforeSend(xhr, settings) === false) {
                return false;
            }
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", Cookies.get('csrftoken'));
            }
        }
    });
})();

但是无论如何,如果我在 $.ajax() 调用中指定了另一个 beforeSend,这种方式就没有运气了。还是有阴影的。

事实上,在jQuery Event的jQuery文档中,设置beforeSend来自$.ajax调用或$.ajaxSetup被称为Local Event,但在当前情况下,使用称为 Global Event$(document).ajaxSend() 更合适。


最终解决方案

如果您想在 ajax 发送上添加多个全局事件处理器,请不要在 $.ajaxSetup 上设置。

改为使用 ajaxSend 事件!

http://api.jquery.com/ajaxSend/

因此代码可能如下所示:

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(document).ajaxSend(function(event, xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !settings.crossDomain) {
        xhr.setRequestHeader("X-CSRFToken", Cookies.get('csrftoken'));
    }
});