javascript - Promisiunile mele nu mai funcționează în jQuery 1.8


Acest fragment de cod a funcționat în 1.7.2 atât cu callback-uri de succes/eroare, cât și cu callback-uri de tip promisiune. În 1.8.2, callback-urile de succes/eroare încă funcționează, dar promisiunile nu. Bănuiesc că linia return dfd.promise(jqXHR); este problema, dar nu sunt sigur.

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

Actualizare: Iată cererea mea ajax care eșuează:

$.ajax({
        url: someFunctionToGetUrl(),
        // works
        //success: callback,
        //error: ajaxErrorHandler
    }).then(
        [callback],
        [errorback, ajaxErrorHandler]
    );
};

Răspuns #1

Editare: Aceasta este o eroare în documentație, dar comportamentul este intenționat. API-ul s-a schimbat astfel încât deferred.then se comportă acum ca deferred.pipe și nu mai permite trecerea de array-uri, dar documentația nu a fost actualizată pentru a reflecta acest lucru.

Bug-uri asociate:

  • github: deferred.then se comportă acum ca deferred.pipe, dar documentația este depășită
  • Urmăritor de erori jQuery: Tichet #12765: deferred.then([SuccessArrayFuncs], failFunc) nu funcționează așa cum este descris

Soluția pe care o descriu la sfârșitul răspunsului meu inițial de mai jos se aplică în continuare.

Răspuns original:

Mi se pare o eroare jQuery. Dacă transmiți o singură referință de funcție ca prim argument, funcționează, dar nu dacă transmiți un array de funcții:

http://jsfiddle.net/tunDH/

Dar, documentația spune că un șir de funcții este perfect acceptabil:

doneCallbacks   O funcție sau un șir de funcții, apelate atunci când Deferred este rezolvat.

Și ai dreptate. Funcționează cu jQuery 1.7: http://jsfiddle.net/tunDH/1/

O soluție alternativă ar fi să înfășurați toate apelurile funcțiilor dvs. într-o singură funcție, în loc să le puneți într-un tablou:

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

Probabil va trebui să faci același lucru și cu callback-urile de eroare, dar nu am testat asta.