javascript - how to overwrite the success function via JQuery ajaxSend event - Stack Overflow

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

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){
        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;});

upon AJAX I do see 'ajax' in the console, but upon success I can't see the start and the end debug msges..

What do I do wrong?

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){
        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;});

upon AJAX I do see 'ajax' in the console, but upon success I can't see the start and the end debug msges..

What do I do wrong?

Share asked Aug 17, 2012 at 10:19 ciochPepciochPep 2,5924 gold badges26 silver badges31 bronze badges 6
  • Related: stackoverflow./questions/293668/… – pimvdb Commented Aug 17, 2012 at 10:31
  • thanks, but it doesn't answer my question, ajaxComplete fires after the browser gets the HTTP response, i am asking about ajaxSend which fires before the HTTP request – ciochPep Commented Aug 17, 2012 at 10:39
  • You're right. I was just pointing at the answer which says that callbacks are bound to be run and that you can't prevent that. Granted it's not exactly your question; I'm interested in a solution as well. – pimvdb Commented Aug 17, 2012 at 10:42
  • Other people and I need something that works without JQuery. We wish that other people will provide code that can do that without jQuery..I have upvoted your answer. thanks! – ciochPep Commented Aug 22, 2012 at 13:30
  • What I mean is that I don't mind that you are using jQuery to do what you do, but you can't assume that the developer is using jQuery in order to initiate AJAX calls – ciochPep Commented Aug 22, 2012 at 13:31
 |  Show 1 more ment

3 Answers 3

Reset to default 7

What you're trying to acplish 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();

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.plete -- 
$.ajaxTransport -- $.fn.ajaxSend -- send the actual request -- 
option.dataFilter --  fire the success/error callbacks -- 
$.fn.ajaxSuccess/$.fn.ajaxError -- fire the plete callbacks --  
$.fn.ajaxComplete -- $.fn.ajaxStop(if needed)

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

You could use closures to acplish 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");
}));

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744911103a4600555.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信