У меня есть загрузчик, и я хочу изучить асинхронные и отложенные тайминги. Это внешний тег сценария, динамически вставляемый - без встроенной задержки.
Сначала я боролся с пониманием того, почему асинхронность велась как отсрочка - она выполнялась после DOMContentLoaded .
С 2000 DOM-элементами асинхронный запуск показывает, что он может выполняться до DOMContentLoaded. Он загружается с локального диска. При извлечении из хоста имеет смысл выполнять асинхронные сценарии в ожидании ответа. Так что это работает.
Затем я перешел к тесту отложенного и неожиданного .. Теперь я бьюсь с шуткой, почему defer ведет себя как асинхронно - выполняется до DOMContentLoaded !
При наличии 100000 элементов DOM, которым потребовалось более 30 с, выполнение сценария все еще происходило до DOMContentLoaded. Что не так?
Вот соответствующие детали, которые я проверял ...
loader.js
window.addEventListener('DOMContentLoaded', function() {
console.log("DOMContentLoaded");
});
var s = document.head.appendChild(document.createElement('script'))
// s.async = true; s.defer = false;
s.async = false; s.defer = true;
s.src = "script.js"
console.log("Fetch script");
script.js
console.log("Execute script");
index.html
<html>
<head>
<script src="loader.js"></script>
</head>
<body>
<script> window.ti = performance.now() </script>
--- put here every html you can find ---
<script>
var n = document.getElementsByTagName('*').length
var t = parseInt(performance.now() - ti) / 1000
document.write("<br>Parsed " + n + " elements in " + t + " s ")
</script>
</body>
</html>
Консоль в FF и Chrome
Fetch script
Execute script
DOMContentLoaded
Отложенный скрипт никогда не должен выполняться до того, как DOM будет готов к использованию .
Теперь у нас есть случай, когда DOMContentLoaded срабатывает до того, как DOM появится на экране. Как?
Редактировать # 1
Остерегайтесь DOMContentLoaded - я хотел, чтобы "dom content проанализировал" !!!
(так что это была ошибка в коде - или в моем уме)
Исправление (спасибо Пойнти) - по моим словам ...
Отложенные сценарии выполняются после анализа dom, но dom все еще загружается. Когда отложенные сценарии и возможные события выполняются, запускается DOMContentLoaded.
Так что мне нужен какой-то "DOMContent Parsed ". Лучшее, что я нашел, это событие readystatechange и document.readyState ...
Давайте расширим loader.js этой строкой:
s.onload = function(){ console.log(document.readyState) }
При достаточном количестве доменов в консоли Chrome и Firefox отображается:
Fetch script
Execute script
loading
DOMContentLoaded
Это означает, что сценарий отсрочки выполняется, пока DOM загружает !
Да да - это загрузка, пока DOMContentLoaded. Позор, что readyState не скажет КОГДА дом разбирается! Я тоже пытался ..
document.addEventListener('readystatechange', function() {
console.log(">>" + document.readyState);
});
Это не срабатывает при «загрузке», потому что он уже запущен, но он говорит «интерактивные» ПОСЛЕ отложенных загруженных сценариев и говорит «завершено», где находится DOMContentLoaded (они одинаковы?), И больше сказать нечего.
У меня больше нет идеи о методе или событии, которые запускаются в / когда dom анализируется. Это должно быть перед продолжением загрузки других вещей, чтобы получить правильную отметку времени перед другими таймингами!
Больше нечего найти! Нет ничего больше, чем первая точка в Living Standard - Последнее обновление 15 апреля 2019 раздел 12.2.7 Конец (даже шутка заголовка со мной): Это readystatechange, который должен делать «интерактивный» до никаких скриптов, но это практически не . Почему?
Мне кажется, что readyState содержит ошибку в локальном index.html, превышающем 2000 элементов, потому что я могу выполнить отложенный скрипт до того, как он скажет «интерактивный». Теперь это определенно понятно, когда вы помещаете этот readyState в скрипт (я забыл), и он говорит «загрузка», это означает, что большой HTML все еще загружается, пока он выполняется:
script.js
console.log("Execute script " + document.readyState);
Вывод : Иногда defer ведет себя как асинхронный, а async как отсроченный