Hier ist ein erfundenes Beispiel dafür, was los ist: 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 "Alles erledigt!" Wird angezeigt, nachdem alle zurückgestellten Aufgaben abgeschlossen wurden, $.when()
scheint jedoch nicht zu wissen, wie mit einem Array von zurückgestellten Objekten umgegangen werden soll. "Alles erledigt!" geschieht zuerst, weil das Array kein verzögertes Objekt ist, also geht jQuery vor und geht davon aus, dass es gerade fertig ist.
Ich weiß, dass man die Objekte wie $.when(deferred1, deferred2, ..., deferredX)
folgt an die Funktion übergeben könnte, aber es ist nicht bekannt, wie viele verzögerte Objekte in dem tatsächlichen Problem, das ich zu lösen versuche, ausgeführt werden.
javascript
jquery
argument-passing
jquery-deferred
.when
Adamjford
quelle
quelle
$.when.apply
überhaupt kein Array verwenden , um das gleiche Ergebnis zu erzielen.Antworten:
Verwenden Sie Folgendes, um ein Array von Werten an eine Funktion zu übergeben, die normalerweise erwartet, dass es sich um separate Parameter handelt.
Function.prototype.apply
In diesem Fall benötigen Sie also:Siehe http://jsfiddle.net/YNGcm/21/
In ES6 können Sie stattdessen den
...
Spread-Operator verwenden:In beiden Fällen
.then
müsste dieser Handler dasarguments
Array verarbeiten, um das Ergebnis jedes Versprechens abzurufen , da es unwahrscheinlich ist, dass Sie im Voraus wissen, wie viele formale Parameter der Handler benötigt .quelle
$.when
-f.apply(ctx, my_array)
rufenf
mitthis == ctx
und die auf die vorgetragenen Argumente Inhalt vonmy_array
.$
vsnull
als erstem Parameter ist eine Lektüre wert. In diesem speziellen Fall spielt es jedoch keine Rolle.$
weniger tippend alsnull
und Sie sind sicher, wenn sich die$.when
Implementierung ändert (nicht, dass dies in diesem Fall wahrscheinlich ist, aber warum nichtthis
standardmäßig unverändert bleiben ).Die obigen Problemumgehungen (danke!) Beheben das Problem, dass die für die verzögerte
resolve()
Methode bereitgestellten Objekte wiederhergestellt werden, nicht richtig , da jQuery diedone()
undfail()
Rückrufe mit einzelnen Parametern aufruft , nicht mit einem Array. Das heißt, wir müssen dasarguments
Pseudo-Array verwenden, um alle aufgelösten / zurückgewiesenen Objekte zu erhalten, die vom Array der zurückgestellten zurückgesendet werden, was hässlich ist:Da wir eine Reihe von Verzögerungen übergeben haben, wäre es schön, eine Reihe von Ergebnissen zurückzugewinnen. Es wäre auch schön, ein tatsächliches Array anstelle eines Pseudo-Arrays zurückzugewinnen, damit wir Methoden wie verwenden können
Array.sort()
.Hier ist eine Lösung, die von der Methode von when.js inspiriert ist
when.all()
, mit der diese Probleme behoben werden:Jetzt können Sie einfach eine Reihe von zurückgestellten / versprochenen Versprechungen übergeben und eine Reihe von aufgelösten / abgelehnten Objekten in Ihrem Rückruf zurückerhalten, wie folgt:
quelle
var toArray = function (args) { return deferreds.length > 1 ? $.makeArray(args) : [args]; }
anstelle von , um das Problem zu behebenArray.prototype.slice.call
.Sie können die
when
Methode auf Ihr Array anwenden :Wie arbeiten Sie mit einem Array von jQuery Deferreds?
quelle
Wenn Sie mehrere parallele AJAX-Anrufe aufrufen, haben Sie zwei Möglichkeiten, die jeweiligen Antworten zu verarbeiten.
Promises'
Array,$.when
daspromise
s akzeptiert, und sein Rückruf.done
wird aufgerufen, wenn allepromise
s mit den entsprechenden Antworten erfolgreich zurückgegeben wurden.Beispiel
quelle
$.when
.for ... in
eines Arrays?!)(not recommended)
2.Nicht zustimmen -for ... in
ist in Ordnung, da das Array nur die Eigenschaften enthält, die benötigt werden (keine zusätzlichen Eigenschaften). Danke trotzdemArray.prototype
. In jedem Fall ist es für nicht leistungskritischen Code besser,.map
anstelle einerfor
/push
-Schleife zu verwenden, zvar promises = capitalCities.map(ajaxRequest); $.when.apply($, promises).then(fillCountryCapitals)
. B. - Job erledigt.Als einfache Alternative, die nicht benötigt
$.when.apply
oderarray
können Sie das folgende Muster verwenden ein einziges Versprechen für mehr parallelen Versprechen zu generieren:z.B
Anmerkungen:
promise = promise.then(newpromise)
quelle
then()
Aufrufen auf ähnliche Weise der Fall ist. Das Verhalten bei$.when
ist, so zu handeln, wie es parallel ist (nicht verkettet). Bitte versuchen Sie es, bevor Sie eine nützliche Alternative wegwerfen, da es funktioniert :)Ich möchte einen anderen mit $ .each vorschlagen:
Wir können die Ajax-Funktion wie folgt deklarieren:
Teil des Codes, in dem wir ein Array von Funktionen mit Ajax zum Senden erstellen:
Und Funktionen mit dem Senden von Ajax aufrufen:
quelle
Wenn Sie transpilieren und Zugriff auf ES6 haben, können Sie die Spread-Syntax verwenden, die jedes iterierbare Element eines Objekts als diskretes Argument anwendet, genau so, wie es
$.when()
benötigt wird.MDN Link - Spread-Syntax
quelle
Wenn Sie angleJS oder eine Variante der Q-Versprechen-Bibliothek verwenden, haben Sie eine
.all()
Methode, die genau dieses Problem löst.Siehe die vollständige API:
https://github.com/kriskowal/q/wiki/API-Reference#promiseall
https://docs.angularjs.org/api/ng/service/$q
quelle
.map
hier aber na ja).Ich hatte einen sehr ähnlichen Fall, in dem ich in jeder Schleife postete und dann in einigen Feldern das HTML-Markup aus den vom Ajax empfangenen Zahlen festlegte. Ich musste dann eine Summe der (jetzt aktualisierten) Werte dieser Felder erstellen und in ein Gesamtfeld einfügen.
Daher bestand das Problem darin, dass ich versuchte, eine Summe für alle Nummern zu erstellen, aber noch keine Daten von den asynchronen Ajax-Aufrufen zurückgekommen waren. Ich musste diese Funktionalität in einigen Funktionen vervollständigen, um den Code wiederverwenden zu können. Meine äußere Funktion wartet auf die Daten, bevor ich dann einige Dinge mit dem vollständig aktualisierten DOM mache.
quelle