Wenn Sie Skripte nicht dynamisch laden oder sie als defer
o async
dann werden die Skripte in der Reihenfolge geladen, in der sie auf der Seite erscheinen. Dabei spielt es keine Rolle, ob es sich um ein externes Skript oder ein Inline-Skript handelt - sie werden in der Reihenfolge ausgeführt, in der sie auf der Seite vorkommen. Inline-Skripte, die nach externen Skripten kommen, werden so lange gehalten, bis alle externen Skripte, die vor ihnen kamen, geladen und ausgeführt wurden.
Async-Skripte (unabhängig davon, wie sie als async angegeben sind) werden in einer nicht vorhersehbaren Reihenfolge geladen und ausgeführt. Der Browser lädt sie parallel, und es steht ihm frei, sie in beliebiger Reihenfolge auszuführen.
Es gibt keine vorhersehbare Reihenfolge bei mehreren asynchronen Vorgängen. Wenn man eine vorhersehbare Reihenfolge bräuchte, müsste man sie kodieren, indem man sich für Ladebenachrichtigungen von den asynchronen Skripten registriert und Javascript-Aufrufe manuell aneinanderreiht, wenn die entsprechenden Dinge geladen werden.
Wenn ein Skript-Tag dynamisch eingefügt wird, hängt es vom Browser ab, wie sich die Ausführungsreihenfolge verhält. Sie können sehen, wie sich Firefox verhält in dieser Referenzartikel . Kurz gesagt, die neueren Versionen von Firefox setzen ein dynamisch hinzugefügtes Skript-Tag standardmäßig auf async, sofern das Skript-Tag nicht anders festgelegt wurde.
Ein Skript-Tag mit async
kann ausgeführt werden, sobald es geladen ist. Der Browser kann den Parser sogar anhalten und das Skript ausführen, sobald er etwas anderes tut. Es kann also wirklich fast jederzeit ausgeführt werden. Wenn das Skript im Cache gespeichert wurde, kann es fast sofort ausgeführt werden. Wenn das Skript eine Weile braucht, um zu laden, kann es ausgeführt werden, nachdem der Parser fertig ist. Das Einzige, was man sich bei async
ist, dass sie jederzeit ablaufen kann und dass die Zeit nicht vorhersehbar ist.
Ein Skript-Tag mit defer
wartet, bis der gesamte Parser fertig ist und führt dann alle Skripte aus, die mit defer
in der Reihenfolge, in der sie angetroffen wurden. So können Sie mehrere Skripte, die voneinander abhängen, als defer
. Sie werden alle verschoben, bis der Dokumentenparser fertig ist, aber sie werden in der Reihenfolge ausgeführt, in der sie gefunden wurden, wobei ihre Abhängigkeiten erhalten bleiben. Ich denke an defer
wie die Skripte in eine Warteschlange gestellt werden, die verarbeitet wird, nachdem der Parser fertig ist. Technisch gesehen kann der Browser die Skripte jederzeit im Hintergrund herunterladen, aber sie werden nicht ausgeführt oder blockieren den Parser, bis der Parser mit dem Parsen der Seite und dem Parsen und Ausführen aller Inline-Skripte fertig ist, die nicht als defer
o async
.
Hier ist ein Zitat aus diesem Artikel:
Skripte, die in ein Skript eingefügt werden, werden in IE und WebKit asynchron ausgeführt, aber synchron in Opera und Firefox vor Version 4.0.
Der relevante Teil der HTML5-Spezifikation (für neuere konforme Browser) lautet aquí . Darin wird viel über asynchrones Verhalten geschrieben. Offensichtlich gilt diese Spezifikation nicht für ältere Browser (oder nicht konforme Browser), deren Verhalten Sie wahrscheinlich testen müssen, um es zu bestimmen.
Ein Zitat aus der HTML5-Spezifikation:
Dann ist die erste der folgenden Optionen zu wählen, die die Situation beschreibt befolgt werden:
Wenn das Element ein src-Attribut hat, und das Element ein defer Attribut hat, und das Element als "Parser-inserted" gekennzeichnet wurde, und das Element kein async-Attribut hat T am Ende der Liste der Skripte hinzugefügt werden, die ausgeführt werden, wenn das Dokument ausgeführt wird, das mit dem Dokument des Parsers verbunden ist, der das Element erstellt hat.
Die Aufgabe, die die Quelle der Netzwerkaufgabe auf die der Abrufalgorithmus abgeschlossen ist, muss das Element auf "bereit zur Parser-Ausführung" setzen. Der Parser wird die Ausführung des Skripts übernehmen.
Wenn das Element ein src-Attribut hat, und das Element als "Parser-inserted" gekennzeichnet wurde und das Element kein async-Attribut hat Das Element ist das anhängige, das Parsing blockierende Skript des Dokuments von des Parsers, der das Element erstellt hat. (Es kann nur ein solches Skript pro Dokument geben.)
Die Aufgabe, die von der Quelle der Netzwerkaufgabe auf die Taskleiste gelegt wird der Abrufalgorithmus abgeschlossen ist, muss das Element auf "bereit zu Parser-Ausführung" setzen. Der Parser wird die Ausführung des Skripts übernehmen.
Wenn das Element kein src-Attribut hat und das Element als "Parser-inserted" gekennzeichnet ist und das Dokument des HTML-Parsers oder XML-Parser, der das Skriptelement erstellt hat, ein Style Sheet hat, das Skripte blockiert Das Element ist das ausstehende Parsing des Dokuments des Parsers, der das Element erstellt hat. (Es kann nur ein solches Skript pro Dokument geben.)
Setzt das Flag "bereit für die Parser-Ausführung" des Elements. Der Parser wird die Ausführung des Skripts übernehmen.
Wenn das Element ein src-Attribut hat, kein async-Attribut hat, und das Flag "force-async" nicht gesetzt ist T am Ende der Liste der Skripte hinzugefügt werden, die so schnell wie möglich nacheinander ausgeführt werden wie möglich in Verbindung mit dem Dokument des Skriptelements zum Zeitpunkt der zum Zeitpunkt des Starts des Algorithmus zur Vorbereitung eines Skripts.
Die Aufgabe, die die Quelle der Netzwerkaufgabe einmal in die Aufgabenwarteschlange stellt Die Aufgabe, die die Netzwerk-Task-Quelle in die Warteschlange stellt, nachdem der Abrufalgorithmus abgeschlossen ist, muss die folgenden Schritte ausführen:
Wenn das Element jetzt nicht das erste Element in der Liste ist das so schnell wie möglich in der Reihenfolge ausgeführt wird, in der es hinzugefügt wurde oben, dann markieren Sie das Element als bereit b ohne das Skript noch auszuführen.
Ausführung: Führen Sie den Skriptblock aus, der dem ersten Skript entspricht Skriptelement in dieser Liste von Skripten entspricht, die in der Reihenfolge so schnell wie möglich wie möglich.
Entfernen Sie das erste Element aus dieser Liste von Skripten, die ausgeführt werden sollen so schnell wie möglich ausführen.
Wenn diese Liste von Skripten, die in der Reihenfolge so bald wie möglich ausgeführt wird noch nicht leer ist und der erste Eintrag bereits als bereit, dann springen Sie zurück zum Schritt mit der Bezeichnung Ausführung.
Wenn das Element ein src-Attribut hat Das Element muss angezeigt werden Menge von Skripten hinzugefügt werden, die so bald wie möglich nach dem Dokument des Skriptelements zu dem Zeitpunkt, zu dem der Algorithmus zur Vorbereitung eines Skripts gestartet wird.
Die Aufgabe, die die Quelle der Netzwerkaufgabe einmal in die Aufgabenwarteschlange stellt der Abrufalgorithmus die dann das Element aus der Menge der Skripts entfernen, die ausgeführt werden, sobald so schnell wie möglich ausführen.
Ansonsten Der User-Agent muss sofort die auch wenn bereits andere Skripte ausgeführt werden.
Wie sieht es mit Javascript-Modulskripten aus? type="module"
?
Javascript hat jetzt Unterstützung für das Laden von Modulen mit einer Syntax wie dieser:
<script type="module">
import {addTextToBody} from './utils.mjs';
addTextToBody('Modules are pretty cool.');
</script>
Oder, mit src
Attribut:
<script type="module" src="http://somedomain.com/somescript.mjs">
</script>
Alle Skripte mit type="module"
werden automatisch mit dem defer
Attribut. Dadurch werden sie parallel (wenn nicht inline) zu anderen Ladevorgängen der Seite heruntergeladen und dann der Reihe nach ausgeführt, aber erst nachdem der Parser fertig ist.
Modulskripte können auch mit der async
Attribut, das Inline-Modulskripte so schnell wie möglich ausführt, ohne zu warten, bis der Parser fertig ist und ohne zu warten, bis die async
Skript in einer bestimmten Reihenfolge im Verhältnis zu anderen Skripten.
Es gibt ein sehr nützliches Zeitdiagramm, das den Abruf und die Ausführung verschiedener Kombinationen von Skripten, einschließlich Modulskripten, hier in diesem Artikel zeigt: Laden von Javascript-Modulen .