Если вы не загружаете скрипты динамически или не помечаете их как defer
или async
, тогда скрипты загружаются в порядке, указанном на странице. Неважно, является ли это внешним скриптом или встроенным скриптом - они выполняются в порядке, в котором они встречаются на странице. Встроенные сценарии, которые идут после внешних сценариев, сохраняются до тех пор, пока все внешние сценарии, которые были до них, не загружены и запущены.
Асинхронные сценарии (независимо от того, как они указаны как асинхронные) загружаются и выполняются в непредсказуемом порядке. Браузер загружает их параллельно, и он может запускать их в любом порядке.
Там нет предсказуемого порядка среди нескольких асинхронных вещей. Если требуется предсказуемый порядок, его необходимо кодировать путем регистрации уведомлений о загрузке из асинхронных сценариев и ручной последовательности вызовов javascript при загрузке соответствующих объектов.
Когда тег сценария вставляется динамически, поведение порядка выполнения будет зависеть от браузера. Вы можете увидеть, как Firefox ведет себя в этой справочной статье . Короче говоря, более новые версии Firefox по умолчанию динамически добавляют тег сценария к асинхронному, если тег сценария не был установлен иначе.
Тег скрипта с async
может быть запущен, как только он будет загружен. Фактически, браузер может приостановить анализатор от всего, что он делал, и запустить этот скрипт. Таким образом, он действительно может работать практически в любое время. Если сценарий был кэширован, он может запуститься практически сразу. Если сценарий загружается некоторое время, он может запуститься после того, как анализатор завершит работу. Следует помнить одну вещь async
: он может работать в любое время, и это время не предсказуемо.
Тег сценария с defer
ожиданием, пока не будет выполнен весь анализатор, а затем запускает все сценарии, помеченные знаком, defer
в том порядке, в котором они были обнаружены. Это позволяет пометить несколько сценариев, которые зависят друг от друга, как defer
. Все они будут отложены до тех пор, пока анализатор документов не будет завершен, но они будут выполняться в том порядке, в котором они были найдены, сохраняя свои зависимости. Я думаю, defer
что сценарии помещаются в очередь, которая будет обработана после выполнения синтаксического анализа. Технически браузер может загружать сценарии в фоновом режиме в любое время, но он не будет выполнять или блокировать синтаксический анализатор до тех пор, пока синтаксический анализатор не завершит синтаксический анализ страницы и синтаксический анализ и запуск любых встроенных сценариев, которые не отмечены defer
или async
.
Вот цитата из этой статьи:
Сценарии с вставленными сценариями выполняются асинхронно в IE и WebKit, но синхронно в Opera и Firefox до 4.0.
Соответствующая часть спецификации HTML5 (для новых совместимых браузеров) здесь . Там много написано об асинхронном поведении. Очевидно, что эта спецификация не относится к более старым браузерам (или браузерам с плохой совместимостью), поведение которых вам, вероятно, придется проверить, чтобы определить.
Цитата из спецификации HTML5:
Затем следует использовать первый из следующих параметров, описывающих ситуацию:
Если элемент имеет атрибут src, а элемент имеет атрибут defer, и элемент помечен как «вставленный парсером», а элемент не имеет асинхронного атрибута
. Элемент должен быть добавлен в конец списка. сценарии, которые будут выполняться после завершения анализа документа, связанного с документом синтаксического анализатора, создавшего элемент.
Задача, которую источник сетевой задачи помещает в очередь задач после завершения алгоритма выборки, должна установить флаг элемента «готов к выполнению синтаксическим анализатором». Парсер будет обрабатывать выполнение скрипта.
Если элемент имеет атрибут src, и элемент помечен как «вставленный синтаксическим анализатором», и элемент не имеет асинхронного атрибута, то
этот элемент является ожидающим сценарием блокировки синтаксического анализа документа анализатора, создавшего элемент. (За один раз может быть только один такой скрипт для каждого документа.)
Задача, которую источник сетевой задачи помещает в очередь задач после завершения алгоритма выборки, должна установить флаг элемента «готов к выполнению синтаксическим анализатором». Парсер будет обрабатывать выполнение скрипта.
Если элемент не имеет атрибута src, и элемент был помечен как «вставленный синтаксический анализатор», а документ Document для анализатора HTML или синтаксического анализатора XML, который создал элемент script, имеет таблицу стилей, которая блокирует сценарии . в ожидании сценария синтаксического анализа Документа синтаксического анализатора, который создал элемент. (За один раз может быть только один такой скрипт для каждого документа.)
Установите флаг элемента "готов к выполнению парсером". Парсер будет обрабатывать выполнение скрипта.
Если элемент имеет атрибут src, не имеет атрибута async и не имеет установленного флага «force-async» Элемент должен быть добавлен в конец списка сценариев, которые будут выполняться по порядку как можно скорее с документом элемента скрипта во время запуска алгоритма подготовки скрипта.
Задача, которую источник сетевой задачи помещает в очередь задач после завершения алгоритма выборки, должна выполнить следующие шаги:
Если элемент не является первым элементом в списке сценариев, который будет выполняться по порядку, как можно скорее, к которому он был добавлен выше, то пометьте элемент как готовый, но отмените эти шаги, пока не выполнив сценарий.
Выполнение: Выполните блок сценария, соответствующий первому элементу сценария в этом списке сценариев, который будет выполнен по порядку как можно скорее.
Удалите первый элемент из этого списка сценариев, которые будут выполняться по порядку как можно скорее.
Если этот список сценариев, которые будут выполняться по порядку в кратчайшие сроки, все еще не пуст и первая запись уже помечена как готовая, вернитесь к шагу, помеченному как выполнение.
Если элемент имеет атрибут src Элемент должен быть добавлен в набор сценариев, которые будут выполняться как можно быстрее документа Document элемента script в момент запуска алгоритма подготовки сценария.
Задача, которую источник сетевой задачи помещает в очередь задач после завершения алгоритма выборки, должна выполнить блок сценария, а затем удалить элемент из набора сценариев, который будет выполнен как можно скорее.
В противном случае пользовательский агент должен немедленно выполнить блок сценария, даже если другие сценарии уже выполняются.
Как насчет скриптов модуля Javascript type="module"
?
Javascript теперь имеет поддержку загрузки модуля с синтаксисом, подобным этому:
<script type="module">
import {addTextToBody} from './utils.mjs';
addTextToBody('Modules are pretty cool.');
</script>
Или с src
атрибутом:
<script type="module" src="http://somedomain.com/somescript.mjs">
</script>
Всем сценариям type="module"
автоматически присваивается defer
атрибут. Это загружает их параллельно (если не встроено) с другой загрузкой страницы, а затем запускает их по порядку, но после того, как анализатор завершен.
Скриптам модуля также может быть присвоен async
атрибут, который будет запускать встроенные скрипты модуля как можно скорее, не дожидаясь окончания синтаксического анализа и не дожидаясь запуска async
скрипта в каком-либо определенном порядке относительно других скриптов.
Есть довольно полезная временная диаграмма, которая показывает выборку и выполнение различных комбинаций сценариев, включая сценарии модуля, здесь в этой статье: Загрузка модуля Javascript .