简体   繁体   中英

jQuery AJAX `always` isn't “always” called

Specifically, when an error is thrown in the done (or fail ) handler, then always handler is simply not called.

I've "fixed" this like so:

xhr.done(delayThrow(function(response) { /* .. do stuff .. */ }));

function delayThrow(fn) {
    return function() {
        try {
            fn.apply(this,arguments);
        } catch(e) {
            setTimeout(function() {
                throw e;
            },10);
        }
    };
}

This works, and (to my surprise) the call stack is left intact*. But it seems like a very hackish solution. Is there a better way, or am I approaching this wrong?

*I assume this is because the exception object is already created and it's just being thrown without factoring in later call stacks like the setTimeout

So, my guess is that the always callback is (indeed) a bit misleading and only fires when an error occurred during the request, as opposed to after it's already done.

Seems like deferred.then() does the job and gets called in every case. However, this only seems to fire with jQuery 3+, which is why I can't post a SO sample (limited to version 2 apparently).

Demo here: https://jsfiddle.net/78ux6jhL/

Note that deferred.then() takes 3 callback parameters, first one when the initial request was successful, second one when it failed. Just pass the same function twice to emulate the actuallyAlways you wanted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM