2010-01-10 32 views
141

Ich hatte den Eindruck, dass JavaScript immer asynchron war. Ich habe jedoch gelernt, dass es Situationen gibt, in denen dies nicht der Fall ist (dh DOM-Manipulationen). Gibt es irgendwo eine gute Referenz, wann es synchron ist und wann es asynchron ist? Beeinflusst jQuery das überhaupt?Wann ist JavaScript synchron?

+10

Immer mit Ausnahme von Ajax. – defau1t

+0

Akzeptierte Antwort ist falsch und irreführend, bitte überprüfen Sie es. –

Antwort

187

JavaScript ist immer synchron und Single-Thread. Wenn Sie einen JavaScript-Code auf einer Seite ausführen, wird derzeit kein anderes JavaScript auf dieser Seite ausgeführt.

JavaScript ist nur asynchron in dem Sinne, dass es beispielsweise Ajax-Aufrufe ausführen kann. Der Code hört auf, ausgeführt zu werden, bis der Aufruf (erfolgreich oder nicht) zurückkehrt, zu welchem ​​Zeitpunkt der Rückruf synchron ausgeführt wird. Zu diesem Zeitpunkt wird kein anderer Code ausgeführt. Es wird keinen anderen laufenden Code unterbrechen.

JavaScript-Timer arbeiten mit dieser Art von Callback.

JavaScript als asynchron zu beschreiben ist vielleicht irreführend. Es ist genauer zu sagen, dass JavaScript synchron und single-threaded mit verschiedenen Callback-Mechanismen ist.

jQuery hat eine Option für Ajax-Aufrufe, um sie synchron zu machen (mit der Option async: false). Anfänger könnten versucht sein, dies falsch zu benutzen, weil es ein traditionelleres Programmiermodell erlaubt, an das man mehr gewöhnt sein könnte. Der Grund, warum es problematisch ist, ist, dass diese Option alle JavaScript auf der Seite bis zum Ende blockieren wird, einschließlich aller Event-Handler und Timer.

+28

Entschuldigung, ich habe diese Anweisung nicht ganz verstanden. "Der Code wird nicht mehr ausgeführt, bis der Aufruf (erfolgreich oder fehlerhaft) zurückkehrt". Könntest du das ausarbeiten?Wie kann diese Aussage wahr sein, wenn Sie auch sagen: "Es wird keinen anderen laufenden Code unterbrechen"; Sprechen Sie nur in der ersten Anweisung über Callback-Code? Bitte erleuchte mich. – krishna

+0

Beachten Sie auch [Ist Javascript single-threaded garantiert?] (Http://stackoverflow.com/q/2734025/1048572) - die Antwort ist Nr. – Bergi

+2

Nettuts hat ein Tutorial, das ziemlich gut darin ist, die Grundlagen von async hier zu erklären : http://net.tutsplus.com/tutorials/javascript-ajax/event-based-programming-what-async-has-over-sync/ – RobW

89

JavaScript ist single-threaded, und Sie arbeiten die ganze Zeit an einer normalen synchronen Code-Flow-Ausführung.

Gute Beispiele für das asynchrone Verhalten, das JavaScript haben kann, sind Ereignisse (Benutzerinteraktion, Ajax-Anfrageergebnisse, etc.) und Timer, im Grunde Aktionen, die jederzeit passieren können.

Ich würde Ihnen empfehlen, einen Blick auf die folgenden Artikel zu geben:

Dieser Artikel wird Ihnen helfen, die Single-Thread-Natur von JavaScript und wie Timer arbeiten intern zu verstehen und wie asynchrone JavaScript-Ausführung funktioniert.

async http://ejohn.org/files/427px-Timers.png

119

JavaScript ist single threaded und hat ein synchrones Ausführungsmodell. Single-Threading bedeutet, dass jeweils ein Befehl ausgeführt wird. Synchron bedeutet nacheinander, d. H. Eine Codezeile wird zur Zeit ausgeführt, damit der Code erscheint. In JavaScript passiert also immer eine Sache.

Ausführungskontext

Die JavaScript-Engine interagiert mit anderen Motoren im Browser. Im JavaScript-Ausführungsstapel befindet sich unten ein globaler Kontext. Wenn wir Funktionen aufrufen, erstellt die JavaScript-Engine neue Ausführungskontexte für die jeweiligen Funktionen. Wenn die aufgerufene Funktion ihren Ausführungskontext verlässt, wird sie aus dem Stapel herausgeholt, und dann wird der nächste Ausführungskontext aufgerufen und so weiter ...

Zum Beispiel

function abc() 
{ 
    console.log('abc'); 
} 


function xyz() 
{ 
    abc() 
    console.log('xyz'); 
} 
var one = 1; 
xyz(); 

In dem obigen Code ein globaler Ausführungskontext erstellt wird und in diesem Zusammenhang var one wird gespeichert und sein Wert wird 1 sein ..., wenn der xyz() Aufruf aufgerufen wird, dann Ein neuer Ausführungskontext wird erstellt, und wenn wir irgendeine Variable in der xyz-Funktion definiert hätten, würden diese Variablen im Ausführungskontext von xyz() gespeichert werden. In der xyz-Funktion rufen wir abc() auf und dann wird der abc() Ausführungskontext erzeugt und auf den Ausführungsstapel gesetzt ... Wenn nun abc() beendet wird, wird der Kontext aus dem Stapel herausgeholt, dann wird der xyz() -Kontext entnommen stack und dann wird der globale Kontext angezeigt ...

Jetzt über asynchrone Rückrufe; asynchron bedeutet mehr als eins gleichzeitig.

Genau wie der Ausführungsstapel gibt es die Ereigniswarteschlange. Wenn wir über ein Ereignis in der JavaScript-Engine benachrichtigt werden möchten, können wir dieses Ereignis abhören und dieses Ereignis wird in die Warteschlange gestellt. Zum Beispiel ein Ajax-Anfrage-Event oder ein HTTP-Anfrage-Event.

Wenn der Ausführungsstapel leer ist, wie in obigem Codebeispiel gezeigt, schaut die JavaScript-Engine regelmäßig auf die Ereigniswarteschlange und sieht, ob ein Ereignis gemeldet werden muss. Zum Beispiel gab es in der Warteschlange zwei Ereignisse, eine Ajax-Anfrage und eine HTTP-Anfrage. Es sieht auch aus, ob es eine Funktion gibt, die auf diesem Ereignistrigger ausgeführt werden muss ... So wird die JavaScript-Engine über das Ereignis benachrichtigt und kennt die entsprechende Funktion, die für dieses Ereignis ausgeführt werden soll Handler-Funktion, im Beispielfall, z AjaxHandler() wird aufgerufen und wie immer, wenn eine Funktion aufgerufen wird, wird ihr Ausführungskontext in den Ausführungskontext gesetzt und nun wird die Ausführung der Funktion beendet und die Ereignis - Ajax - Anfrage wird ebenfalls aus der Ereigniswarteschlange entfernt. Wenn AjaxHandler() das beendet Der Ausführungsstapel ist leer, sodass die Engine erneut die Ereigniswarteschlange betrachtet und die Ereignishandlerfunktion der HTTP-Anforderung ausführt, die als nächste in der Warteschlange war. Es ist wichtig zu beachten, dass die Ereigniswarteschlange nur verarbeitet wird, wenn der Ausführungsstapel leer ist.

Zum Beispiel den folgenden Code, der den Ausführungsstapel und die Ereigniswarteschlangenbehandlung durch die Javascript-Engine erläutert.

function waitfunction() { 
    var a = 5000 + new Date().getTime(); 
    while (new Date() < a){} 
    console.log('waitfunction() context will be popped after this line'); 
} 

function clickHandler() { 
    console.log('click event handler...'); 
} 

document.addEventListener('click', clickHandler); 


waitfunction(); //a new context for this function is created and placed on the execution stack 
console.log('global context will be popped after this line'); 

Und

<html> 
    <head> 

    </head> 
    <body> 

     <script src="program.js"></script> 
    </body> 
</html> 

nun die Webseite laufen und auf der Seite klicken und die Ausgabe auf der Konsole sehen. Der Ausgang

waitfunction() context will be popped after this line 
global context will be emptied after this line 
click event handler... 

Der JavaScript-Engine den Code wird synchron in dem Ausführungskontext Teil wie erläuterte ausgeführt wird, wird der Browser Dinge in Ereigniswarteschlange asynchron setzen. So können die Funktionen, die sehr lange dauern, die Ereignisbehandlung unterbrechen. Dinge, die in einem Browser wie Ereignisse passieren, werden auf diese Weise von JavaScript gehandhabt. Wenn ein Listener ausgeführt werden soll, wird die Engine ihn ausführen, wenn der Ausführungsstapel leer ist. Und Ereignisse werden in der Reihenfolge verarbeitet, in der sie auftreten, so dass der asynchrone Teil davon handelt, was außerhalb der Maschine passiert, d. H. Was die Engine tun soll, wenn diese äußeren Ereignisse passieren.

Also JavaScript ist immer synchron.

+11

Diese Antwort ist sehr klar, es sollte mehr Upvotes bekommen. –

+4

Sicherlich die beste Erklärung für das asynchrone Verhalten von Javascript, das ich gelesen habe. –

+1

Schöne Erklärung des Ausführungskontexts und der Warteschlange. –