Es gibt keine Zeit, in Javascript zu schneiden. Javascript ist single-threaded (außer für Web-Worker, die wir hier nicht diskutieren). Ein Thread der JavaScript-Ausführung wird bis zum Abschluss ausgeführt.
In Ihrem ersten Codebeispiel macht die Animation ihre Sache und wenn sie vollständig fertig ist, ruft sie Ihre my_cpu_heavy_function
.
In Ihrem zweiten Codebeispiel initialisiert die Animation selbst und setzt einen Timer für das erste Animationsschritt ist. Dann kehrt es zurück und geht in die nächste Codezeile. Die Animation hat erst begonnen (und in der Zukunft einen Timer gesetzt, um etwas mehr Arbeit zu leisten) - sie ist noch nicht abgeschlossen. Dann läuft Ihr my_cpu_heavy_function
und es hackt die gesamte Javascript-Ausführung, bis es fertig ist. Die Animation läuft überhaupt nicht, während my_cpu_heavy_function
läuft. Wenn dies abgeschlossen ist, wird das Timer-Ereignis ausgelöst, das der Animationssatz ausgelöst hat, und die Animation wird ausgeführt.
Animationen können "wie Zeit" aussehen, aber sie sind nicht wirklich. jQuery-Animationen bewegen sich einen Schritt in der Animation und setzen dann einen Timer für eine kleine Zeitspanne in der Zukunft und sie kehren zum System zurück. Wenn dieses Timer-Ereignis ausgelöst wird, führt jQuery den nächsten Schritt in der Animation aus und so weiter.Wenn ein Timer-Ereignis ausgelöst wird, wird ein Timer-Ereignis in die JavaScript-Ereigniswarteschlange eingefügt. Wenn gerade kein Javascript läuft, wird der Timer-Callback sofort gestartet. Wenn JavaScript gerade ausgeführt wird, befindet sich das Timer-Ereignis nur in der Ereigniswarteschlange, bis der aktuelle JavaScript-Thread beendet ist. Wenn dieser Thread beendet ist, sucht javascript in der Ereigniswarteschlange nach, ob Ereignisse warten. Wenn dies der Fall ist, ruft es den Ereignis-Callback auf.
Als solche gibt es wirklich keine Zeit für verschiedene Stücke von Javascript schneiden. Zwei Codeabschnitte, die ausgeführt werden sollen, erhalten nicht einige CPU-Zyklen, wie dies bei echten Threads im nativen Code der Fall wäre. In Javascript läuft ein Stück Code bis es fertig ist und dann kann das nächste Event gestartet werden. In Dingen wie JavaScript-basierte Animationen kann das Time Slicing etwas simuliert werden, indem man eine kleine Menge Arbeit verrichtet und dann einen Timer für eine zukünftige Zeit setzt und zum System zurückkehrt. Sobald Sie mit der Ausführung fertig sind, kann ein anderer Teil von Javascript ausgeführt werden, aber es wird auch so lange ausgeführt, bis es fertig ist. Wenn alle Teile von Javascript nur kleine Mengen von Arbeit machen und dann einen Timer für ihre nächste Arbeit setzen, dann können sie alle zusammenarbeiten und es wird so aussehen, als würde es Zeit, aber es funktioniert nur wegen der Zusammenarbeit zwischen allen. Wenn eine Funktion wie my_cpu_heavy_function
kommt und die CPU für eine Weile schwört, läuft niemand sonst während dieser Zeit. Die Animation wurde gestoppt, während my_cpu_heavy_function
ausgeführt wurde.
Einige Operationen in einem Browser werden durch systemeigenen Code im Browser ausgeführt (z. B. Ajax-Aufrufe, Laden von Bildern usw.). Diese asynchronen Tasks können im Hintergrund ausgeführt werden, während JavaScript ausgeführt wird. Sie werden jedoch erst dann Javascript benachrichtigen, wenn der aktuelle Thread der JavaScript-Ausführung beendet ist und ein neuer mit dem Benachrichtigungs-Callback gestartet werden kann.
Als Beispiel nehmen wir an, wir haben ein Bild, das 1 Sekunde zum Laden und eine CPU-intensive Funktion dauert, die 5 Sekunden dauert. Wir haben dann diesen Code:
var img = new Image();
img.onload = function() {
alert("image is loaded now");
}
img.src = "xxx.jpg";
longFunctionThatTakesFiveSecondsToRun();
Wenn wir diesen Code ausführen, auch wenn das Bild dauert nur 1 Sekunde intern im Browser zu laden, werden die onload-Handler nicht aufgerufen, bis longFunctionThatTakesFiveSecondsToRun()
5 Sekunden laufen getan wird später . Es muss warten, bis der aktuelle Ausführungsthread abgeschlossen ist, bevor das Onload-Ereignis verarbeitet werden kann.
Wenn Sie mehr über JavaScript-Event-Warteschlangen und asynchrone Operationen wissen wollen, finden Sie diese im Zusammenhang Antworten:
How does JavaScript handle AJAX responses in the background?
Race conditions with JavaScript event handling?
Can JS event handlers interrupt execution of another handler?
Do I need to be concerned with race conditions with asynchronous Javascript?
Asynchronous Sachen kann noch geschehen (z. B. Herunterladen von Remote-Ressourcen s), obwohl dies bei 'animate' nicht der Fall ist - es ist nur so, dass die * events/callbacks * verzögert werden, bis kein anderer Code auf der Seite ausgeführt wird. –
@ pst: Der Rückruf ist nur ein weiterer Teil des asynchronen Codes, der nach dem letzten animierenden asynchronen Code ausgeführt wird. Der gesamte Async-Code ist blockiert, solange ein synchroner Code ausgeführt wird. Der Synchronisierungscode lässt keine Asynchronisierung zu, bis sie abgeschlossen ist. –
In Bezug auf Ihren aktualisierten Kommentar, ja (Herunterladen von Remote-Ressourcen), aber das ist außerhalb der JavaScript-Laufzeit. –