6

我试图在 ajaxsend 事件上覆盖成功函数,但它在这里不起作用是代码:

    $(document).ajaxSend(function(event,xhr,options){
        console.log('ajaxSend');
        var tempSuccess = options.success;
        options.success = function(data, textStatus, jqXHR){
            console.log('start');
            tempSuccess(data, textStatus, jqXHR);
            console.log('end');
        }; xhr.success = options.success;});

在 AJAX 上,我确实在控制台中看到了“ajax”,但成功后我看不到开始和结束调试消息。

我做错了什么?

4

3 回答 3

7

你试图完成的事情不能用ajaxSend. 问题是它显然适用于原始对象和对象ajaxSend的副本,因此修改不会产生任何影响。您可以使用以下代码轻松测试它:xhroptions

$(document).ajaxSend(function(event, xhr, options){
    delete options.success;
    console.log(options.success);   // undefined
});
$.ajax({
    url: "test.html",
    success: function() { console.log("this will be printed nevertheless"); }
});


所以你不能ajaxSend用来覆盖成功回调。相反,您将不得不“破解”jQuery 的 AJAX 函数:

// closure to prevent global access to this stuff
(function(){
    // creates a new callback function that also executes the original callback
    var SuccessCallback = function(origCallback){
        return function(data, textStatus, jqXHR) {
            console.log("start");
            if (typeof origCallback === "function") {
                origCallback(data, textStatus, jqXHR);
            }
            console.log("end");
        };
    };

    // store the original AJAX function in a variable before overwriting it
    var jqAjax = $.ajax;
    $.ajax = function(settings){
        // override the callback function, then execute the original AJAX function
        settings.success = new SuccessCallback(settings.success);
        jqAjax(settings);
    };
})();

现在您可以$.ajax像往常一样简单地使用:

$.ajax({
    url: "test.html",
    success: function() {
        console.log("will be printed between 'start' and 'end'");
    }
});

据我所知,任何 jQuery 的 AJAX 函数(例如$.get().load())在内部使用$.ajax,所以这应该适用于通过 jQuery 完成的每个 AJAX 请求(虽然我还没有测试过......)。



通过破解XMLHttpRequest.prototype. 请注意,以下内容在 IE 中不起作用,它ActiveXObject使用XMLHttpRequest.

(function(){
    // overwrite the "send" method, but keep the original implementation in a variable
    var origSend = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.send = function(data){
        // check if onreadystatechange property is set (which is used for callbacks)
        if (typeof this.onreadystatechange === "function") {
            // overwrite callback function
            var origOnreadystatechange = this.onreadystatechange;
            this.onreadystatechange = function(){
                if (this.readyState === 4) {
                    console.log("start");
                }
                origOnreadystatechange();
                if (this.readyState === 4) {
                    console.log("end");
                }
            };
        }
        // execute the original "send" method
        origSend.call(this, data);
    };
})();

用法(就像通常的 XMLHttpRequest 一样):

var xhr = new XMLHttpRequest();
xhr.open("POST", "test.html", true);
xhr.onreadystatechange = function(){
    if (xhr.readyState === 4) {
        console.log("will be printed between 'start' and 'end'");
    }
};
xhr.send();
于 2012-08-17T17:50:53.797 回答
0

因为在 ajaxSend 之前使用了 option.success。当它被使用时,它被添加到延迟对象中。

之后,你改变option.success,什么都不会发生。

因此,您必须在使用之前对其进行更改。过程是:

$.ajaxPrefilter -- $.fn.ajaxStart(if needed) -- option.beforeSend -- 
USE option.success and option.error and option.complete -- 
$.ajaxTransport -- $.fn.ajaxSend -- send the actual request -- 
option.dataFilter --  fire the success/error callbacks -- 
$.fn.ajaxSuccess/$.fn.ajaxError -- fire the complete callbacks --  
$.fn.ajaxComplete -- $.fn.ajaxStop(if needed)

因此,您可以更改“$.ajaxPrefilter”或“option.beforeSend”中的 option.success。

于 2020-12-24T09:21:17.567 回答
-1

您可以使用闭包来完成您所需要的:

function closure(handler) {
    return function(ev, xhr, options) {
        console.log("start");
        handler(ev, xhr, options);
        console.log("stop");
    }
}

$(document).ajaxSend(closure(function(ev, xhr, options) {
    console.log("hello");
}));
于 2012-08-17T17:01:56.600 回答