how to overwrite the success function via JQuery ajaxSend event

前端 未结 3 928
走了就别回头了
走了就别回头了 2021-01-05 12:45

I am trying to overwrite the success function upon ajaxsend event but it doesnt work here is the code:

    $(document).ajaxSend(function(event,xhr,options){
         


        
相关标签:
3条回答
  • 2021-01-05 13:14

    What you're trying to accomplish can't be done with ajaxSend. The problem is that ajaxSend apparently works with a copy of the original xhr and options objects, so the modifications won't have any effect. You can easily test this with the following code:

    $(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"); }
    });
    


    So you can't use ajaxSend to overwrite the success callbacks. Instead, you will have to "hack" jQuery's AJAX function:

    // 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);
        };
    })();
    

    Now you can simply use $.ajax as usual:

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

    As far as I know, any of jQuery's AJAX functions (such as $.get() or .load()) internally use $.ajax, so this should work with every AJAX request done via jQuery (I haven't tested this though...).



    Something like that should also work with "pure" JavaScript by hacking the XMLHttpRequest.prototype. Note that the following won't work in IE, which uses ActiveXObject instead of 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);
        };
    })();
    

    Usage (just like a usual 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();
    
    0 讨论(0)
  • 2021-01-05 13:14

    You could use closures to accomplish what you need:

    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");
    }));
    
    0 讨论(0)
  • 2021-01-05 13:19

    Because the option.success is used before ajaxSend. When it was used,it was added to the Deferred Object.

    After that,you change the option.success, nothing will happen.

    So, you must change it before is was used. the process is:

    $.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)
    

    So, you can change the option.success in "$.ajaxPrefilter" or "option.beforeSend".

    0 讨论(0)
提交回复
热议问题