Почему он показывает defer как async и async как defer? Получите "разобранный случай" правильно! А нет? - PullRequest
0 голосов
/ 21 апреля 2019

У меня есть загрузчик, и я хочу изучить асинхронные и отложенные тайминги. Это внешний тег сценария, динамически вставляемый - без встроенной задержки.

Сначала я боролся с пониманием того, почему асинхронность велась как отсрочка - она ​​выполнялась после 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 как отсроченный

1 Ответ

2 голосов
/ 21 апреля 2019

Определение атрибута defer на странице MDN для элементов сценария :

Этот логический атрибут установлен для указания браузеру, что сценарий предназначен длявыполняется после анализа документа, но до запуска DOMContentLoaded.

Скрипты с атрибутом defer будут препятствовать запуску события DOMContentLoaded до тех пор, пока скрипт не загрузится и не завершит оценку.

То, что вы видите, это предполагаемое поведение.

...