2012-09-08 8 views
7

oder ecmascript, aber ich frage mich, ob es mehr auf die genaue Umsetzung ankommt, wie es tatsächlich passiert.Wie erfolgt die Zeitaufteilung in Javascript?

Javascript ist technisch single-threaded.

aber wenn ich etwas tun, wie

$myDIv.animate({ 
    height:"100px" 
}); 

macht es einen Unterschied, wenn ich

A.

$myDIv.animate({ 
    height:"100px" 
}, null, my_cpu_heavy_function); 

oder B.

$myDIv.animate({ 
    height:"100px" 
}); 
my_cpu_heavy_function(); 

tun, weil in der zweite war die Animation Ich würde für die Verarbeitungszeit mit der CPU-Heavy-Funktion kämpfen und so würde das Aussehen der Animation leiden, oder?

So stoppt Javascript am Ende eines synchronen Codeblock ausgeführt wird oder ist sie schneiden einen Block an jedem beliebigen Punkt aus asynchron verarbeitet zu laufen einen anderen Block zu ermöglichen?

Antwort

4

macht es einen Unterschied, wenn ich A oder B zu tun

Ja, es wird einen Unterschied machen.

Die zweite Version kämpft nicht so sehr um Bearbeitungszeit. Es ist eher so, als ob die my_cpu_heavy_function die gesamte Verarbeitungszeit belegt, sobald sie beginnt, vorausgesetzt, sie ist synchron.

Mit anderen Worten, sobald ein wenig Synchroncode beginnt, ist es nicht bis zum vollständigen unabhängig von einem zeitlich asynchronen Code beenden, die Ausführung geplant werden kann. Der asynchrone Code muss immer auf den Abschluss des synchronen Codes warten.

Also wird passieren, dass die Animation beginnt, und führen Sie ihre Initialisierung, aber dann my_cpu_heavy_function wird sofort gestartet, und blockieren Sie den Rest der Animation, bis es abgeschlossen ist.

+0

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. –

+0

@ 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. –

+0

In Bezug auf Ihren aktualisierten Kommentar, ja (Herunterladen von Remote-Ressourcen), aber das ist außerhalb der JavaScript-Laufzeit. –

5

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?

+0

hi, ich habe ein paar Tabs geschlossen und diese Frage auf Updates überprüft und mich schlecht gefühlt, weil du eine so detaillierte Antwort gegeben hast und niemand geantwortet hat. viel von dem, was du gesagt hast, weiß ich, obwohl ich hauptsächlich in Javascript programmiere. Ich weiß, Javascript berührt nicht direkt den Prozessor und ich weiß, wie man Rodeo-Threads und über die CLR (im. NET). Es ist genau so, als ob du viel Zeit damit verbracht hast, etwas zu sagen, weil du nicht das Wissen respektiert hast, dass jemand eine Frage über dummes altes Javascript stellt. Sie wissen das offensichtlich sehr gut und möchten neuen Programmierern helfen. also vielen Dank. –