Jeśli nie ładujesz dynamicznie skryptów ani nie zaznaczasz ich jako defer
lub async
, wówczas skrypty są ładowane w kolejności podanej na stronie. Nie ma znaczenia, czy jest to skrypt zewnętrzny czy skrypt wbudowany - są one wykonywane w kolejności, w jakiej występują na stronie. Skrypty wbudowane, które pojawiają się po skryptach zewnętrznych, są wstrzymywane do momentu załadowania i uruchomienia wszystkich skryptów zewnętrznych poprzedzających je.
Skrypty asynchroniczne (niezależnie od tego, jak są określone jako asynchroniczne) ładują się i działają w nieprzewidywalnej kolejności. Przeglądarka ładuje je równolegle i można je uruchamiać w dowolnej kolejności.
Nie ma przewidywalnego porządku wśród wielu rzeczy asynchronicznych. Gdyby ktoś potrzebował przewidywalnego porządku, musiałby zostać zakodowany poprzez rejestrację powiadomień o ładowaniu ze skryptów asynchronicznych i ręczne sekwencjonowanie wywołań javascript, gdy odpowiednie rzeczy zostaną załadowane.
Gdy znacznik skryptu jest wstawiany dynamicznie, sposób zachowania kolejności wykonywania zależeć będzie od przeglądarki. W tym artykule referencyjnym możesz zobaczyć, jak zachowuje się Firefox . Krótko mówiąc, nowsze wersje Firefoksa domyślnie domyślnie dodają dynamicznie znacznik skryptu do asynchronizacji, chyba że znacznik skryptu został ustawiony inaczej.
Tag skryptu z async
można uruchomić natychmiast po załadowaniu. W rzeczywistości przeglądarka może zatrzymać analizator składni od wszystkiego, co robił i uruchomić ten skrypt. Tak naprawdę może działać prawie w dowolnym momencie. Jeśli skrypt został buforowany, może zostać uruchomiony niemal natychmiast. Jeśli skrypt ładuje się chwilę, może działać po zakończeniu parsera. Jedyną rzeczą, o której należy pamiętać, async
jest to, że może ona działać w dowolnym momencie i że czas ten nie jest przewidywalny.
Tag skryptu z defer
oczekiwaniem na zakończenie całego parsera, a następnie uruchamia wszystkie skrypty oznaczone defer
w kolejności ich napotkania. Umożliwia to oznaczenie kilku skryptów, które zależą od siebie jako defer
. Wszystkie zostaną odłożone na później, aż do zakończenia parsera dokumentów, ale wykonają je w kolejności, w jakiej napotkano, zachowując swoje zależności. Myślę, że defer
skrypty są upuszczane w kolejce, która zostanie przetworzona po zakończeniu parsera. Technicznie rzecz biorąc, przeglądarka może pobierać skrypty w tle w dowolnym momencie, ale nie wykonają ani nie zablokują parsera, dopóki parser nie zakończy parsowania strony oraz parsowania i uruchamiania wszelkich wbudowanych skryptów, które nie są oznaczone defer
lub async
.
Oto cytat z tego artykułu:
skrypty wstawione w skrypcie wykonują się asynchronicznie w IE i WebKit, ale synchronicznie w Operze i Firefoksie wcześniejszym niż 4.0.
Odpowiednia część specyfikacji HTML5 (dla nowszych zgodnych przeglądarek) znajduje się tutaj . Wiele się tam pisze o zachowaniu asynchronicznym. Oczywiście ta specyfikacja nie dotyczy starszych przeglądarek (lub źle dostosowanych przeglądarek), których zachowanie prawdopodobnie musiałbyś przetestować w celu ustalenia.
Cytat ze specyfikacji HTML5:
Następnie należy zastosować pierwszą z następujących opcji opisujących sytuację:
Jeśli element ma atrybut src, a element ma atrybut odroczenia, a element został oflagowany jako „wstawiony przez analizator składni”, a element nie ma atrybutu asynchronicznego,
element należy dodać na końcu listy skrypty, które zostaną wykonane, gdy dokument zakończy parsowanie powiązane z dokumentem analizatora składni, który utworzył element.
Zadanie, które źródło zadania sieciowego umieszcza w kolejce zadań po zakończeniu algorytmu pobierania, musi ustawić flagę elementu „gotowe do wykonania przez analizator składni” elementu. Analizator składni obsłuży wykonywanie skryptu.
Jeśli element ma atrybut src, a element został oflagowany jako „wstawiony przez analizator składni”, a element nie ma atrybutu asynchronicznego,
to element jest oczekującym skryptem blokującym parsowanie dokumentu analizatora składni, który utworzył element. (W danym dokumencie może istnieć tylko jeden taki skrypt).
Zadanie, które źródło zadania sieciowego umieszcza w kolejce zadań po zakończeniu algorytmu pobierania, musi ustawić flagę elementu „gotowe do wykonania przez analizator składni” elementu. Analizator składni obsłuży wykonywanie skryptu.
Jeśli element nie ma atrybutu src, a element został oflagowany jako „wstawiony przez analizator składni”, a dokument analizatora składni HTML lub analizatora składni XML, który utworzył element skryptu, ma arkusz stylów blokujący skrypty Element jest oczekujący skrypt blokujący parsowanie dokumentu parsera, który utworzył element. (W danym dokumencie może istnieć tylko jeden taki skrypt).
Ustaw flagę elementu „gotowy do wykonania przez analizator składni”. Analizator składni obsłuży wykonywanie skryptu.
Jeśli element ma atrybut src, nie ma atrybutu asynchronicznego i nie ma ustawionej flagi „force-async” Element należy dodać na końcu listy skryptów, które zostaną wykonane w kolejności, jak najszybciej powiązane z Dokumentem elementu skryptu w momencie przygotowania algorytmu skryptu.
Zadanie, które źródło zadania sieciowego umieszcza w kolejce zadań po zakończeniu algorytmu pobierania, musi uruchomić następujące kroki:
Jeśli element nie jest teraz pierwszym elementem na liście skryptów, które wykonają się w jak najkrótszym czasie, do którego został dodany powyżej, oznacz element jako gotowy, ale przerwij te kroki, nie wykonując jeszcze skryptu.
Wykonanie: Wykonaj blok skryptu odpowiadający pierwszemu elementowi skryptu na tej liście skryptów, które zostaną wykonane w kolejności tak szybko, jak to możliwe.
Usuń pierwszy element z tej listy skryptów, które będą wykonywane w kolejności tak szybko, jak to możliwe.
Jeśli ta lista skryptów, które będą uruchamiane w kolejności tak szybko, jak to możliwe, nadal nie jest pusta, a pierwszy wpis został już oznaczony jako gotowy, wróć do wykonania oznaczonego krokiem.
Jeśli element ma atrybut src Element należy dodać do zestawu skryptów, które wykonają dokument Dokumentu elementu skryptowego w możliwie najkrótszym czasie w momencie przygotowania algorytmu skryptowego.
Zadanie, które źródło zadania sieciowego umieszcza w kolejce zadań po zakończeniu algorytmu pobierania, musi wykonać blok skryptu, a następnie usunąć element ze zbioru skryptów, który zostanie wykonany jak najszybciej.
W przeciwnym razie Agent użytkownika musi natychmiast wykonać blok skryptu, nawet jeśli inne skrypty już działają.
Co ze skryptami modułów JavaScript type="module"
?
JavaScript obsługuje teraz ładowanie modułów o takiej składni:
<script type="module">
import {addTextToBody} from './utils.mjs';
addTextToBody('Modules are pretty cool.');
</script>
Lub z src
atrybutem:
<script type="module" src="http://somedomain.com/somescript.mjs">
</script>
Wszystkie skrypty z type="module"
automatycznie otrzymują defer
atrybut. Spowoduje to pobranie ich równolegle (jeśli nie w linii) z innym ładowaniem strony, a następnie uruchomi je w kolejności, ale po zakończeniu parsera.
Skrypty modułowe mogą również otrzymać async
atrybut, który będzie uruchamiał wbudowane skrypty modułowe tak szybko, jak to możliwe, nie czekając na zakończenie parsera i nie czekając na uruchomienie async
skryptu w określonej kolejności w stosunku do innych skryptów.
Istnieje całkiem przydatny wykres na osi czasu, który pokazuje pobieranie i wykonywanie różnych kombinacji skryptów, w tym skryptów modułowych w tym artykule: Ładowanie modułu JavaScript .