Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My promises no longer working in jQuery 1.8

This code snippet worked in 1.7.2 with both success/error callbacks as well as promises style callbacks. With 1.8.2 the success/error callbacks still work but the promises do not. My hunch is that the return dfd.promise(jqXHR); line is the problem but im not certain.

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {

    // Don't infinitely recurse
    originalOptions._retry = isNaN(originalOptions._retry)
        ? Common.auth.maxExpiredAuthorizationRetries
        : originalOptions._retry - 1;

    // set up to date authorization header with every request
    jqXHR.setRequestHeader("Authorization", Common.auth.getAuthorizationHeader());

    // save the original error callback for later
    if (originalOptions.error)
        originalOptions._error = originalOptions.error;

    // overwrite *current request* error callback
    options.error = $.noop();

    // setup our own deferred object to also support promises that are only invoked
    // once all of the retry attempts have been exhausted
    var dfd = $.Deferred();
    jqXHR.done(dfd.resolve);

    // if the request fails, do something else yet still resolve
    jqXHR.fail(function () {
        var args = Array.prototype.slice.call(arguments);

        if (jqXHR.status === 401 && originalOptions._retry > 0) {

            // refresh the oauth credentials for the next attempt(s)
            // (will be stored and returned by Common.auth.getAuthorizationHeader())
            Common.auth.handleUnauthorized();

            // retry with our modified
            $.ajax(originalOptions).then(dfd.resolve, dfd.reject);

        } else {
            // add our _error callback to our promise object
            if (originalOptions._error)
                dfd.fail(originalOptions._error);
            dfd.rejectWith(jqXHR, args);
        }
    });

    // NOW override the jqXHR's promise functions with our deferred
    return dfd.promise(jqXHR);
});

Update: Here is my ajax request that fails:

$.ajax({
        url: someFunctionToGetUrl(),
        // works
        //success: callback,
        //error: ajaxErrorHandler
    }).then(
        [callback],
        [errorback, ajaxErrorHandler]
    );
};
like image 728
ryan Avatar asked Oct 17 '12 14:10

ryan


1 Answers

Edit: This is a documentation bug, but the behavior is by design. The api changed such that deferred.then now behaves like deferred.pipe and no longer allows arrays to be passed in, but the documentation hasn't been updated to reflect that.

Related bugs:

  • github: deferred.then now behaves like deferred.pipe but the documentation is stale
  • jQuery Bug Tracker: Ticket #12765: deferred.then([SuccessArrayFuncs],failFunc) does not work as described

The workaround I describe at the end of my original answer below still applies.


Original answer:

It looks like a jQuery bug to me. If you pass in a single function reference as the first argument, it works, but not if you pass in an array of functions:

http://jsfiddle.net/tunDH/

But, the documentation says an array of functions is just fine:

doneCallbacks   A function, or array of functions, called when the Deferred is resolved.

And, you are right. It does work with jQuery 1.7: http://jsfiddle.net/tunDH/1/

A workaround would be to wrap all your function calls inside a single function, instead of inside an array:

$.ajax({ 
    url: someFunctionToGetUrl(), 
    // works 
    //success: callback, 
    //error: ajaxErrorHandler 
}).then( 
    function(){
        callback1.apply(this, arguments);
        callback2.apply(this, arguments);
    }, 
    [errorback, ajaxErrorHandler] 
); 

http://jsfiddle.net/tunDH/2/

You'll probably need to do the same thing with the error callbacks, but I didn't test that.

like image 93
gilly3 Avatar answered Nov 17 '22 06:11

gilly3