Реальный ответ: потому что вы не можете доверять отсрочке.
В концепции отсрочка и асинхронность отличаются следующим образом:
async позволяет загружать скрипт в фоновом режиме без блокировки. Затем, в момент завершения загрузки, рендеринг блокируется, и этот скрипт выполняется. Рендеринг возобновляется после выполнения скрипта.
defer делает то же самое, за исключением утверждений, гарантирующих, что сценарии выполняются в порядке, указанном на странице, и будут выполняться после завершения анализа документа. Поэтому некоторые сценарии могут закончить загрузку, а затем сидеть и ждать сценариев, которые были загружены позже, но появились перед ними.
К сожалению, из-за того, что на самом деле является стандартным сражением, определение defer варьируется от спецификации к спецификации, и даже в самых последних спецификациях не дает полезной гарантии. Как показывают ответы здесь и , этот вопрос демонстрирует, что браузеры по-разному реализуют отсрочку:
- В некоторых ситуациях в некоторых браузерах есть ошибка, из-за которой
defer
скрипты работают не по порядку.
- Некоторые браузеры задерживают событие
DOMContentLoaded
до окончания загрузки скриптов defer
, а некоторые - нет.
- Некоторые браузеры подчиняются
defer
элементам <script>
со встроенным кодом и без атрибута src
, а некоторые игнорируют его.
К счастью, в спецификации, по крайней мере, указано, что асинхронные переопределения отложены. Таким образом, вы можете рассматривать все сценарии как асинхронные и получать широкую поддержку браузера, например:
<script defer async src="..."></script>
98% браузеров, используемых по всему миру, и 99% в США избежат блокировки при таком подходе.
(Если вам нужно дождаться окончания разбора документа, прослушайте событие DOMContentLoaded
или воспользуйтесь удобной функцией .ready()
jQuery. В любом случае вы захотите сделать это, чтобы изящно использовать браузеры, которые не Реализовать defer
вообще.)