Ich hoffe, ich mache mich nicht zum Narren, aber ich versuche zu verstehen, was in diesen beiden Codezeilen passiert:
document.body.innerHTML = 'something';
alert('something else');
Was ich beobachte, ist, dass eine Warnung angezeigt wird, bevor HTML aktualisiert wurde (oder vielleicht, aber die Seite wurde nicht aktualisiert / neu gestrichen / was auch immer)
Überprüfen Sie diesen Codepen, um zu sehen, was ich meine.
Bitte beachten Sie, dass auch Putting alert
in setTimeout(..., 0)
nicht hilft. Es sieht so aus, als ob mehr Ereignisschleifen erforderlich sind innerHTML
, um die Seite tatsächlich zu aktualisieren.
BEARBEITEN:
Ich habe vergessen zu erwähnen, dass ich Chrome verwende, und habe andere Browser nicht überprüft. Sieht so aus, als wäre es nur in Chrome sichtbar. Trotzdem interessiert mich immer noch, warum das passiert.
quelle
Antworten:
Das Festlegen von innerHTML ist synchron, ebenso wie die meisten Änderungen, die Sie am DOM vornehmen können. Das Rendern der Webseite ist jedoch eine andere Geschichte.
(Denken Sie daran, DOM steht für "Document Object Model". Es ist nur ein "Modell", eine Darstellung von Daten. Der Benutzer sieht auf seinem Bildschirm ein Bild davon, wie dieses Modell aussehen sollte. Das Ändern des Modells erfolgt also nicht sofort Ändern Sie das Bild - die Aktualisierung dauert einige Zeit.)
Das Ausführen von JavaScript und das Rendern der Webseite erfolgt separat. Um es vereinfachend, zuerst alle JavaScript auf der Seite ausgeführt wird (von der Ereignisschleife - schauen Sie sich dieses hervorragende Video für weitere Details) und dann nach , dass der Browser auf die Webseite alle Änderungen macht für den Benutzer zu sehen. Aus diesem Grund ist das "Blockieren" eine so große Sache - das Ausführen von rechenintensivem Code verhindert, dass der Browser den Schritt "JS ausführen" übergeht und in den Schritt "Seite rendern" übergeht, wodurch die Seite einfriert oder stottert.
Die Pipeline von Chrome sieht folgendermaßen aus:
Wie Sie sehen können, geschieht das gesamte JavaScript zuerst. Dann wird die Seite gestylt, angelegt, gemalt und zusammengesetzt - das "Rendern". Nicht die gesamte Pipeline führt jeden Frame aus. Dies hängt davon ab, welche Seitenelemente gegebenenfalls geändert wurden und wie sie erneut gerendert werden müssen.
Hinweis:
alert()
Ist auch synchron und wird während des JavaScript-Schritts ausgeführt. Aus diesem Grund wird das Warndialogfeld angezeigt, bevor Sie Änderungen an der Webseite sehen.Sie könnten jetzt fragen: "Moment mal, was genau wird in diesem 'JavaScript'-Schritt in der Pipeline ausgeführt? Wird mein gesamter Code 60 Mal pro Sekunde ausgeführt?" Die Antwort lautet "Nein" und geht zurück auf die Funktionsweise der JS-Ereignisschleife. JS-Code wird nur ausgeführt, wenn er sich im Stapel befindet - von Ereignissen wie Ereignis-Listenern, Zeitüberschreitungen usw. Siehe vorheriges Video (wirklich).
https://developers.google.com/web/fundamentals/performance/rendering/
quelle
Ja, es ist synchron, da dies funktioniert (geben Sie es in Ihre Konsole ein):
Der Grund, warum Sie die Warnung sehen, bevor sich die Seite ändert, ist, dass das Rendern des Browsers mehr Zeit in Anspruch nimmt und nicht so schnell ist, wie Ihr Javascript zeilenweise ausgeführt wird.
quelle
text
in meinem Beispiel) Damit wird Ihre Frage beantwortet, ob es synchron ist. Browser-Rendering vs. Javascript-Ausführung ist Apfel und Orangen :)Die
innerHTML
eigentliche Eigenschaft wird zwar synchron aktualisiert, das durch diese Änderung verursachte visuelle Neuzeichnen erfolgt jedoch asynchron.Das visuelle Rendern des DOM ist in Chrome asynchron und erfolgt erst, nachdem der aktuelle JavaScript-Funktionsstapel gelöscht wurde und der Browser ein neues Ereignis akzeptieren kann. Andere Browser verwenden möglicherweise separate Threads, um JavaScript-Code und das Rendern von Browsern zu verarbeiten, oder sie lassen einige Ereignisse Priorität erhalten, während eine Warnung die Ausführung eines anderen Ereignisses stoppt.
Sie können dies auf zwei Arten sehen:
Wenn Sie
for(var i=0; i<1000000; i++) { }
vor Ihrer Warnung hinzufügen , haben Sie dem Browser genügend Zeit zum erneuten Zeichnen gegeben, dies ist jedoch nicht der Fall, da der Funktionsstapel nicht gelöscht wurde (add
noch ausgeführt wird).Wenn Sie Ihre
alert
asynchrone VerzögerungsetTimeout(function() { alert('random'); }, 1)
verzögern, kann der Neuzeichnungsprozess die durch setTimeout verzögerte Funktion ausführen.0
, möglicherweise weil Chrome0
Zeitüberschreitungen vor anderen Ereignissen (oder zumindest vor Neuzeichnungsereignissen) Priorität in der Ereigniswarteschlange einräumt .quelle
setTimeout(func, 1)
nicht jedes Mal funktioniert hat, überprüfen Sie dieses Video: youtu.be/r8caVE_a5KQ