1. Was ist ein zurückgestelltes Objekt?
Bei der Entwicklung von Websites stoßen wir häufig auf bestimmte JavaScript-Vorgänge, die lange dauern. Darunter gibt es sowohl asynchrone Vorgänge (z. B. Ajax-Lesen von Serverdaten) als auch synchrone Vorgänge (z. B. das Durchlaufen eines großen Arrays), und die Ergebnisse sind nicht sofort verfügbar.
Der übliche Ansatz besteht darin, Rückruffunktionen für sie anzugeben. Das heißt, Sie legen vorab fest, welche Funktionen nach ihrer Ausführung aufgerufen werden sollen.
Allerdings ist jQuery sehr schwach, wenn es um Callback-Funktionen geht. Um dies zu ändern, hat das jQuery-Entwicklungsteam das verzögerte Objekt entworfen.
Einfach ausgedrückt ist das verzögerte Objekt die Callback-Funktionslösung von jQuery. Im Englischen bedeutet defer „Verzögerung“. Die Bedeutung eines verzögerten Objekts besteht also darin, die Ausführung bis zu einem bestimmten Punkt in der Zukunft zu „verzögern“.
Es löst das Problem der Handhabung zeitaufwändiger Vorgänge, bietet eine bessere Kontrolle über diese Vorgänge und eine einheitliche Programmierschnittstelle. Seine Hauptfunktionen lassen sich in vier Punkten zusammenfassen. Im Folgenden lernen wir Schritt für Schritt anhand des Beispielcodes.
2. Kettenschreibmethode der Ajax-Operation
Betrachten wir zunächst die traditionelle Schreibweise der Ajax-Operation von jQuery:
Im obigen Code akzeptiert $.ajax() einen Objektparameter. Dieses Objekt enthält zwei Methoden: Die Erfolgsmethode gibt die Rückruffunktion an, nachdem die Operation erfolgreich war, und die Fehlermethode gibt die Rückruffunktion an, nachdem die Operation fehlgeschlagen ist.
Nach Abschluss der $.ajax()-Operation wird das XHR-Objekt zurückgegeben, wenn Sie eine Version von jQuery verwenden, die niedriger als 1.5.0 ist, und Sie können keine Kettenoperationen ausführen, wenn die Version höher als 1.5.0 ist , können die zurückgegebenen verzögerten Objekte verkettet werden.
Die neue Schreibweise lautet nun:
Wie Sie sehen können, entspricht done() der Erfolgsmethode und fail() der Fehlermethode. Nach der Einführung der Kettenschreibmethode wird die Lesbarkeit des Codes erheblich verbessert.
3. Geben Sie mehrere Rückruffunktionen für denselben Vorgang an
Einer der großen Vorteile des verzögerten Objekts besteht darin, dass Sie mehrere Rückruffunktionen frei hinzufügen können.
Was soll ich am Beispiel des obigen Codes tun, wenn ich nach erfolgreicher Ajax-Operation zusätzlich zur ursprünglichen Rückruffunktion auch eine weitere Rückruffunktion ausführen möchte?
Es ist ganz einfach, fügen Sie es einfach am Ende hinzu.
Sie können beliebig viele Rückruffunktionen hinzufügen und diese werden in der Reihenfolge ausgeführt, in der sie hinzugefügt werden.
4. Geben Sie Rückruffunktionen für mehrere Vorgänge an
Ein weiterer großer Vorteil des verzögerten Objekts besteht darin, dass Sie eine Rückruffunktion für mehrere Ereignisse angeben können, was mit herkömmlichem Schreiben nicht möglich ist.
Bitte schauen Sie sich den folgenden Code an, der eine neue Methode $.when() verwendet:
Die Bedeutung dieses Codes besteht darin, zunächst zwei Operationen $.ajax("test1.html") und $.ajax("test2.html") auszuführen. Wenn beide erfolgreich sind, führen Sie den durch die Funktion done() angegebenen Rückruf aus ; wenn einer oder beide fehlschlagen, wird die durch fail() angegebene Callback-Funktion ausgeführt.
5. Callback-Funktionsschnittstelle für allgemeine Operationen (Teil 1)
Der größte Vorteil des verzögerten Objekts besteht darin, dass es diesen Satz von Rückruffunktionsschnittstellen von Ajax-Operationen auf alle Operationen erweitert. Mit anderen Worten: Jede Operation – ob es sich um eine Ajax-Operation oder eine lokale Operation handelt, ob es sich um eine asynchrone Operation oder eine synchrone Operation handelt – kann verschiedene Methoden des verzögerten Objekts verwenden, um eine Rückruffunktion anzugeben.
Schauen wir uns ein konkretes Beispiel an. Angenommen, es gibt eine zeitaufwändige Wartezeit:
Natürlich werden Sie denken, dass Sie $.when() verwenden können:
Wenn die Methode done() jedoch so geschrieben wird, wird sie sofort ausgeführt und fungiert nicht als Rückruffunktion. Der Grund dafür ist, dass die Parameter von $.when() nur verzögerte Objekte sein können, daher muss wait() neu geschrieben werden:
[Code]
var dtd = $.Deferred(); // Ein neues verzögertes Objekt erstellen
var wait = function(dtd){
var task = function(){
alarm("Ausführung abgeschlossen!");
dtd.resolve(); // Den Ausführungsstatus des verzögerten Objekts ändern
};
setTimeout(tasks,5000);
return dtd;
};
Jetzt gibt die Funktion wait() ein verzögertes Objekt zurück, sodass Kettenoperationen hinzugefügt werden können.
Nachdem die Funktion „wait()“ ausgeführt wurde, wird die durch die Methode „done()“ angegebene Rückruffunktion automatisch ausgeführt.
6. deferred.resolve()-Methode und deferred.reject()-Methode
Wenn Sie genau hinschauen, werden Sie feststellen, dass es in der Funktion wait() oben noch eine weitere Stelle gibt, die ich nicht erklärt habe. Das ist es, was dtd.resolve() macht?
Um dieses Problem zu klären, müssen wir ein neues Konzept „Ausführungsstatus“ einführen. jQuery legt fest, dass verzögerte Objekte drei Ausführungszustände haben: unvollendet, abgeschlossen und fehlgeschlagen. Wenn der Ausführungsstatus „abgeschlossen“ (aufgelöst) ist, ruft das zurückgestellte Objekt sofort die durch die Methode done() angegebene Rückruffunktion auf. Wenn der Ausführungsstatus „fehlgeschlagen“ ist, wird die durch die Methode fail() angegebene Rückruffunktion aufgerufen. Wenn der Ausführungsstatus „nicht erfolgreich“ lautet, „Abgeschlossen“, warten Sie weiter oder rufen Sie die Rückruffunktion auf, die durch die progress()-Methode angegeben wird (hinzugefügt in der jQuery-Version 1.7).
Während der Ajax-Operation im vorherigen Teil ändert das verzögerte Objekt automatisch seinen Ausführungsstatus basierend auf dem Rückgabeergebnis. In der Funktion wait() muss dieser Ausführungsstatus jedoch manuell vom Programmierer angegeben werden. Die Bedeutung von dtd.resolve() besteht darin, den Ausführungsstatus des dtd-Objekts von „unvollendet“ in „abgeschlossen“ zu ändern und so die Methode done() auszulösen.
In ähnlicher Weise gibt es auch eine deferred.reject()-Methode, die den Ausführungsstatus des DTD-Objekts von „unvollständig“ in „fehlgeschlagen“ ändert und dadurch die fail()-Methode auslöst.
7. deferred.promise()-Methode
Es gibt immer noch Probleme mit der oben genannten Schreibweise. Das heißt, dtd ist ein globales Objekt, sodass sein Ausführungsstatus von außen geändert werden kann.
Bitte schauen Sie sich den folgenden Code an:
Ich habe am Ende des Codes eine Zeile von dtd.resolve() hinzugefügt, die den Ausführungsstatus des dtd-Objekts änderte, wodurch die Methode done() sofort ausgeführt wurde und das „Haha, erfolgreich!“ angezeigt wurde. Es erscheint ein Eingabeaufforderungsfeld usw. 5 Nach einigen Sekunden wird das Eingabeaufforderungsfeld „Ausführung abgeschlossen!“ angezeigt.
Um diese Situation zu vermeiden, stellt jQuery die Methode deferred.promise() bereit. Seine Funktion besteht darin, ein anderes zurückgestelltes Objekt für das ursprüngliche zurückgestellte Objekt zurückzugeben. Letzteres öffnet nur Methoden, die sich nicht auf die Änderung des Ausführungsstatus beziehen (z. B. die Methode done() und die Methode fail()), und blockiert Methoden, die sich auf die Änderung des Ausführungsstatus beziehen Ausführungsstatus (z. B. die Methode „resolve()“ und die Methode „reject()“), sodass der Ausführungsstatus nicht geändert werden kann.
Bitte schauen Sie sich den folgenden Code an:
Eine bessere Möglichkeit, es zu schreiben, besteht jedoch, wie von allenm aufgezeigt, darin, das dtd-Objekt in das interne Objekt der Funktion wait() umzuwandeln.
8. Callback-Funktionsschnittstelle für allgemeine Operationen (Mitte)
Eine weitere Möglichkeit, zu verhindern, dass der Ausführungsstatus von außen geändert wird, besteht darin, die Konstruktorfunktion $.Deferred() des verzögerten Objekts zu verwenden.
Zu diesem Zeitpunkt bleibt die Wartefunktion unverändert, wir übergeben sie direkt an $.Deferred():
jQuery legt fest, dass $.Deferred() einen Funktionsnamen (beachten Sie, dass es sich um einen Funktionsnamen handelt) als Parameter akzeptieren kann und das von $.Deferred() generierte verzögerte Objekt als Standardparameter dieser Funktion verwendet wird .
9. Callback-Funktionsschnittstelle für allgemeine Operationen (Teil 2)
Zusätzlich zu den beiden oben genannten Methoden können wir die verzögerte Schnittstelle auch direkt auf dem Warteobjekt bereitstellen.
10. Zusammenfassung: Methoden verzögerter Objekte
Wir haben bereits über die verschiedenen Methoden der verzögerten Objekte gesprochen. Hier ist eine Zusammenfassung:
(1) $.Deferred() generiert ein verzögertes Objekt.
(2) deferred.done() gibt die Rückruffunktion an, wenn der Vorgang erfolgreich ist
(3) deferred.fail() gibt die Rückruffunktion an, wenn der Vorgang fehlschlägt
(4) Wenn deferred.promise() keine Parameter hat, gibt es ein neues verzögertes Objekt zurück und der Betriebsstatus des Objekts kann nicht geändert werden, wenn es Parameter akzeptiert, dient es dazu, die verzögerte Schnittstelle auf dem Parameterobjekt bereitzustellen .
(5) deferred.resolve() Ändert den Ausführungsstatus des verzögerten Objekts manuell in „Abgeschlossen“ und löst so sofort die Methode done() aus.
(6) deferred.reject() Diese Methode ist genau das Gegenteil von deferred.resolve(). Nach dem Aufruf wird der Ausführungsstatus des verzögerten Objekts in „fehlgeschlagen“ geändert, wodurch die Methode fail() ausgelöst wird sofort.
(7) $.when() gibt Rückruffunktionen für mehrere Operationen an.
Zusätzlich zu diesen Methoden verfügt das verzögerte Objekt auch über zwei wichtige Methoden, die im obigen Tutorial nicht behandelt werden.
(8)deferred.then()
Um Ärger zu sparen, können done() und fail() manchmal zusammen geschrieben werden. Dies ist die then()-Methode.
Wenn then() zwei Parameter hat, ist der erste Parameter die Callback-Funktion der done()-Methode und der zweite Parameter die Callback-Methode der fail()-Methode. Wenn then() nur einen Parameter hat, entspricht dies done().
(9) deferred.always()
Diese Methode wird auch zur Angabe der Rückruffunktion verwendet. Ihre Funktion besteht darin, dass sie am Ende immer ausgeführt wird, egal ob deferred.resolve() oder deferred.reject() aufgerufen wird.