Чи можете ви використовувати як асинхронний, так і відкладений атрибути для тегу сценарію HTML?


81

Я хотів би завантажити наступний код JavaScript, використовуючи обидва deferі async:

<script defer async src="/js/somescript.js"></script>

Оскільки deferпідтримується Internet Explorer 5.5+, як ви можете бачити на CanIUse.com , я хотів би витончено повернутися до використання відстрочки, якщо async недоступний. Я вважаю, що краще використовувати Async, коли він доступний, але його не підтримують до Internet Explorer 10.

Моє питання, отже, чи є вказаний код дійсним HTML? Якщо ні, чи можливо створити цю ситуацію за допомогою JavaScript, щоб витончено повернутися до використання deferна сценарії, коли asyncвін недоступний?

Відповіді:


126

З специфікації: https://www.w3.org/TR/2011/WD-html5-20110525/scripting-1.html#attr-script-async

Атрибут defer може бути вказаний, навіть якщо вказаний атрибут async, щоб застарілі веб-браузери, які підтримують лише defer (а не async), поверталися до поведінки defer замість синхронної поведінки блокування, яка є типовою.


5
Це правда ?: 1. як async deferіснує, так і сучасні браузери працюють як async; 2. обоє async deferіснують, старі браузери працюють як deferзамість defaultповедінки
vikyd

Не асинхронізуй і не відкладай робити навпаки? Async буде завантажувати сценарій одночасно, але виконуватиметься після завершення завантаження (призупинення аналізу сторінки), але Defer виконуватиме лише в кінці всього завантаження та аналізу?
Лео Мюллер

3
Якщо присутній атрибут async, то сценарій буде виконаний асинхронно, як тільки він стане доступним. Якщо атрибут async відсутній, але присутній атрибут defer, тоді сценарій виконується, коли сторінка закінчила розбір. В обох випадках завантаження сторінки не блокується.
Дейв

@LeoMuller Ось чому там написано "резервний варіант". Сучасні з них вважають за краще , asyncщоб defer. І так @vikyd. Якщо вам просто байдуже про спадщину, ви ніколи не хочете, щоб обидва були однаково <script>.
Константин Ван

19

Питання в тому, що ви очікуєте від цього? Якщо присутні як async, так і defer , я би очікував, що сценарій буде відкладений і виконаний лише після DOMContentLoaded, коли браузер не працює, але якщо я читаю специфікацію правильно, схоже, defer ігнорується, якщо встановлено async і сценарій завантажений асинхронно, тому виконуватиметься, як тільки стане доступним, що цілком може бути перед DOMContentLoaded і може заблокувати інші ресурси.

Є три можливі режими, які можна вибрати за допомогою цих атрибутів. Якщо присутній атрибут async, то сценарій буде виконаний асинхронно, як тільки він стане доступним. Якщо атрибут async відсутній, але присутній атрибут defer, тоді сценарій виконується, коли сторінка закінчила розбір. Якщо немає жодного атрибута, скрипт отримується та виконується негайно, перш ніж агент користувача продовжить розбір сторінки.

https://www.w3.org/TR/2011/WD-html5-20110525/scripting-1.html#attr-script-async


10

На жаль defer, ігнорується, коли asyncвказано, і asyncзавжди має вищий пріоритет. (Принаймні в Chrome. Чесно кажучи, не тестували в інших браузерах, але я думаю, що результат буде однаковим.)

І особисто я вважаю, що дуже погано те, що deferігнорується. Давайте уявимо ситуацію, коли ми хотіли б, щоб якомога швидше ініціалізувався JS, навіть до завантаження вмісту сторінки. Але ми хочемо, щоб цей скрипт ініціалізувався ДО решти сценаріїв, які цього потребують. Вона повинна бути першою в deferчерзі. Але, на жаль, це не спрацює:

<!-- we want "jQuery" ASAP and still in "defer" queue. But defer is ignored. -->
<script src="jquery.min.js" async defer></script>

<!-- this doesn't blocks the content and can wait the full page load, but requires "jQuery" -->
<script src="some_jquery_plugin.min.js" defer></script>

У цьому зразку файл "some_jquery_plugin.min.js" може бути завантажений і виконаний перед завантаженням jQuery, і він не зможе. :(

Отже, існує 2 способи вирішити проблему: або використовувати лише deferдирективу, або об’єднати всі залежні файли javascript в єдиний JS.


9

Так, його дійсний HTML, і він буде працювати, як очікувалося.

Будь-який сумісний з W3C браузер розпізнає атрибут async і буде правильно обробляти сценарій, тоді як застарілі версії IE розпізнають атрибут defer .

Оскільки обидва атрибути булеві, вам не потрібно призначати будь-яке значення.


Дякую @jandy за ще одну чудову відповідь!
Jasdeep Khalsa

11
"... буде працювати, як очікувалося". Що б ви сподівались це зробити ?!
Patrick Clancey
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.