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