jQuery-callback voor meerdere ajax-oproepen

Ik wil drie ajax-aanroepen doen in een klikgebeurtenis. Elke ajax-oproep voert een afzonderlijke bewerking uit en retourneert gegevens die nodig zijn voor een laatste callback. De oproepen zelf zijn niet van elkaar afhankelijk, ze kunnen allemaal tegelijk gaan, maar ik zou graag nog een laatste keer teruggebeld willen worden als ze alle drie voltooid zijn.

$('#button').click(function() {
    fun1();
    fun2();
    fun3();
//now do something else when the requests have done their 'success' callbacks.
});
var fun1= (function() {
    $.ajax({/*code*/});
});
var fun2 = (function() {
    $.ajax({/*code*/});
});
var fun3 = (function() {
    $.ajax({/*code*/});
});

Antwoord 1, autoriteit 100%

Het lijkt erop dat je hier een aantal antwoorden op hebt, maar ik denk dat er hier iets is dat het vermelden waard is en dat je code aanzienlijk zal vereenvoudigen. jQuery introduceerde de $.whenin v1.5. Het ziet eruit als:

$.when($.ajax(...), $.ajax(...)).then(function (resp1, resp2) {
    //this callback will be fired once all ajax calls have finished.
});

Ik zag het hier niet vermeld, ik hoop dat het helpt.


Antwoord 2, autoriteit 71%

Hier is een callback-object dat ik heb geschreven, waarbij je ofwel een enkele callback kunt activeren zodra ze allemaal zijn voltooid of ze elk hun eigen callback kunnen geven en ze allemaal kunnen activeren zodra ze allemaal zijn voltooid:

KENNISGEVING

Sinds jQuery 1.5+ kunt u de uitgestelde methode gebruiken zoals beschreven in een ander antwoord:

 $.when($.ajax(), [...]).then(function(results){},[...]);

Voorbeeld van uitgesteld hier

voor jQuery < 1.5 werkt het volgende, of als u uw ajax-oproepen op onbekende tijden wilt laten afgaan, zoals hier weergegeven met twee knoppen: afgevuurd nadat op beide knoppen is geklikt

[gebruik]

voor enkelecallback eenmaal voltooid: Werkvoorbeeld

// initialize here
var requestCallback = new MyRequestsCompleted({
    numRequest: 3,
    singleCallback: function(){
        alert( "I'm the callback");
    }
});
//usage in request
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.requestComplete(true);
    }
});
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.requestComplete(true);
    }
});
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.requestComplete(true);
    }
});

elk met hun eigencallback wanneer ze allemaal voltooid zijn: Werkvoorbeeld

//initialize 
var requestCallback = new MyRequestsCompleted({
    numRequest: 3
});
//usage in request
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.addCallbackToQueue(true, function() {
            alert('Im the first callback');
        });
    }
});
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.addCallbackToQueue(true, function() {
            alert('Im the second callback');
        });
    }
});
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.addCallbackToQueue(true, function() {
            alert('Im the third callback');
        });
    }
});

[De code]

var MyRequestsCompleted = (function() {
    var numRequestToComplete, requestsCompleted, callBacks, singleCallBack;
    return function(options) {
        if (!options) options = {};
        numRequestToComplete = options.numRequest || 0;
        requestsCompleted = options.requestsCompleted || 0;
        callBacks = [];
        var fireCallbacks = function() {
            alert("we're all complete");
            for (var i = 0; i < callBacks.length; i++) callBacks[i]();
        };
        if (options.singleCallback) callBacks.push(options.singleCallback);
        this.addCallbackToQueue = function(isComplete, callback) {
            if (isComplete) requestsCompleted++;
            if (callback) callBacks.push(callback);
            if (requestsCompleted == numRequestToComplete) fireCallbacks();
        };
        this.requestComplete = function(isComplete) {
            if (isComplete) requestsCompleted++;
            if (requestsCompleted == numRequestToComplete) fireCallbacks();
        };
        this.setCallback = function(callback) {
            callBacks.push(callBack);
        };
    };
})();

Antwoord 3, autoriteit 9%

Ik zie zelf de noodzaak van een object niet in. Simple heeft een variabele die een geheel getal is. Wanneer u een aanvraag start, verhoogt u het nummer. Wanneer een voltooid is, verlaagt u deze. Als het nul is, zijn er geen verzoeken in behandeling, dus je bent klaar.

$('#button').click(function() {
    var inProgress = 0;
    function handleBefore() {
        inProgress++;
    };
    function handleComplete() {
        if (!--inProgress) {
            // do what's in here when all requests have completed.
        }
    };
    $.ajax({
        beforeSend: handleBefore,
        complete: function () {
            // whatever
            handleComplete();
            // whatever
        }
    });
    $.ajax({
        beforeSend: handleBefore,
        complete: function () {
            // whatever
            handleComplete();
            // whatever
        }
    });
    $.ajax({
        beforeSend: handleBefore,
        complete: function () {
            // whatever
            handleComplete();
            // whatever
        }
    });
});

Antwoord 4, autoriteit 9%

Het is vermeldenswaard dat aangezien $.whenalle ajax-verzoeken als sequentiële argumenten (geen array) verwacht, u gewoonlijk $.whengebruikt met .apply()zoals zo:

// Save all requests in an array of jqXHR objects
var requests = arrayOfThings.map(function(thing) {
    return $.ajax({
        method: 'GET',
        url: 'thing/' + thing.id
    });
});
$.when.apply(this, requests).then(function(resp1, resp2/*, ... */) {
    // Each argument is an array with the following structure: [ data, statusText, jqXHR ]
    var responseArgsArray = Array.prototype.slice.call(this, arguments);
});

Met behulp van de Spread-syntaxis, je kunt deze code nu als volgt schrijven:

$.when(...requests).then((...responses) => {
    // do something with responses
})

Dit komt omdat $.whendit soort argumenten accepteert

$.when(ajaxRequest1, ajaxRequest2, ajaxRequest3);

En niet zo:

$.when([ajaxRequest1, ajaxRequest2, ajaxRequest3]);

Antwoord 5, autoriteit 2%

Ik hou van het idee van hvgotcodes. Mijn suggestie is om een ​​generieke incrementer toe te voegen die het volledige aantal vergelijkt met het benodigde aantal en vervolgens de laatste callback uitvoert. Dit kan worden ingebouwd in de laatste callback.

var sync = {
 callbacksToComplete = 3,
 callbacksCompleted = 0,
 addCallbackInstance = function(){
  this.callbacksCompleted++;
  if(callbacksCompleted == callbacksToComplete) {
   doFinalCallBack();
  }
 }
};

[bewerkt om naam updates weer te geven.]


6

Ik vroeg dezelfde vraag een tijdje geleden en kreeg hier een paar goede antwoorden: Beste manier om een ​​’callback’ toe te voegen na een reeks asynchrone XHR-oproepen

Other episodes