471 Stimmen

Übergeben Sie ein Array von Deferreds an $.when()

Hier ist ein konstruiertes Beispiel dafür: http://jsfiddle.net/adamjford/YNGcm/20/

HTML:

<a href="#">Click me!</a>
<div></div>

JavaScript:

function getSomeDeferredStuff() {
    var deferreds = [];

    var i = 1;
    for (i = 1; i <= 10; i++) {
        var count = i;

        deferreds.push(
        $.post('/echo/html/', {
            html: "<p>Task #" + count + " complete.",
            delay: count
        }).success(function(data) {
            $("div").append(data);
        }));
    }

    return deferreds;
}

$(function() {
    $("a").click(function() {
        var deferreds = getSomeDeferredStuff();

        $.when(deferreds).done(function() {
            $("div").append("<p>All done!</p>");
        });
    });
});

Ich möchte, dass "Alles erledigt!" erscheint, wenn alle aufgeschobenen Aufgaben erledigt sind, aber $.when() scheint nicht zu wissen, wie man mit einem Array von Deferred-Objekten umgeht. "All done!" geschieht zuerst, weil das Array nicht ein Deferred-Objekt ist, so jQuery geht voran und nimmt an, es ist gerade fertig.

Ich weiß, dass man die Objekte an die Funktion übergeben könnte wie $.when(deferred1, deferred2, ..., deferredX) aber es ist nicht bekannt, wie viele Deferred-Objekte es bei der Ausführung des eigentlichen Problems, das ich zu lösen versuche, geben wird.

5voto

Ich möchte eine andere vorschlagen, die $.each verwendet:

  1. Wir können ajax Funktion wie zu deklarieren:

    function ajaxFn(someData) {
        this.someData = someData;
        var that = this;
        return function () {
            var promise = $.Deferred();
            $.ajax({
                method: "POST",
                url: "url",
                data: that.someData,
                success: function(data) {
                    promise.resolve(data);
                },
                error: function(data) {
                    promise.reject(data);
                }
            })
            return promise;
        }
    }
  2. Teil des Codes, wo wir die Erstellung Array von Funktionen mit Ajax zu senden:

    var arrayOfFn = [];
    for (var i = 0; i < someDataArray.length; i++) {
        var ajaxFnForArray = new ajaxFn(someDataArray[i]);
        arrayOfFn.push(ajaxFnForArray);
    }
  3. Und der Aufruf von Funktionen mit dem Senden von Ajax:

    $.when(
        $.each(arrayOfFn, function(index, value) {
            value.call()
        })
    ).then(function() {
            alert("Cheer!");
        }
    )

1voto

relic Punkte 1561

Wenn Sie transpilieren und Zugang zu ES6 haben, können Sie die Spread-Syntax verwenden, die speziell jedes iterierbare Element eines Objekts als diskretes Argument verwendet, genau wie $.when() braucht es.

$.when(...deferreds).done(() => {
    // do stuff
});

MDN-Link - Spread-Syntax

0voto

Cameron Forward Punkte 622

Ich hatte einen sehr ähnlichen Fall, in dem ich in einer Each-Schleife gebucht und dann die HTML-Auszeichnung in einigen Feldern von Zahlen aus der Ajax empfangen. Ich musste dann eine Summe der (jetzt aktualisierten) Werte dieser Felder bilden und in ein Gesamtfeld eingeben.

Das Problem war also, dass ich versuchte, eine Summe über alle Zahlen zu bilden, aber noch keine Daten von den asynchronen Ajax-Aufrufen zurückgekommen waren. Ich musste diese Funktionalität in ein paar Funktionen vervollständigen, um den Code wiederverwenden zu können. Meine äußere Funktion wartet auf die Daten, bevor ich dann gehen und tun einige Dinge mit dem vollständig aktualisierten DOM.

    // 1st
    function Outer() {
        var deferreds = GetAllData();

        $.when.apply($, deferreds).done(function () {
            // now you can do whatever you want with the updated page
        });
    }

    // 2nd
    function GetAllData() {
        var deferreds = [];
        $('.calculatedField').each(function (data) {
            deferreds.push(GetIndividualData($(this)));
        });
        return deferreds;
    }

    // 3rd
    function GetIndividualData(item) {
        var def = new $.Deferred();
        $.post('@Url.Action("GetData")', function (data) {
            item.html(data.valueFromAjax);
            def.resolve(data);
        });
        return def;
    }

-1voto

mastaBlasta Punkte 5480

Wenn Sie AngularJS oder eine Variante der Q-Promise-Bibliothek verwenden, dann haben Sie eine .all() Methode, die genau dieses Problem löst.

var savePromises = [];
angular.forEach(models, function(model){
  savePromises.push(
    model.saveToServer()
  )
});

$q.all(savePromises).then(
  function success(results){...},
  function failed(results){...}
);

sehen Sie die vollständige API:

https://github.com/kriskowal/q/wiki/API-Reference#promiseall

https://docs.angularjs.org/api/ng/service/$q

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X