DOMContentLoaded никогда не срабатывает внутри модуля - PullRequest
0 голосов
/ 05 мая 2020

Меня смущает то, что события не запускаются в конкретном сценарии загрузки модуля ES6. Вот проект Codepen для поддержки моих примеров: https://codepen.io/fchristant/project/editor/AYQkGJ

Рассмотрим этот очень простой модуль app. js:

console.log('in module');
document.addEventListener('DOMContentLoaded', (event) => {
  console.log('DCL:2');
});

Я использую динамический c Импорт ES6 из тегов скрипта в заголовке документа:

<script>
  (async () => {
    const module = await import("./js/app.js");
    console.log('async done');
   })();
</script>

Итак, этот вызывающий код не является модулем (syn c script), динамически загружающим модуль. Поскольку он находится в заголовке документа, а не asyn c или defer, я ожидаю, что он будет запущен немедленно и сделает это блокирующим способом.

Это мои ожидания, но не то, что происходит. В частности, проблема в том, что событие в модуле никогда не запускается. И похоже, что это уже поздно слушать, событие уже произошло. Как такое может быть, учитывая скрипт блокировки в заголовке документа? Это выглядит неблокирующим, но я не понимаю почему.

Для ясности, дискуссия заключается не в том, хорошая это идея или нет, меня прежде всего интересует концептуальный ответ почему это не работает. Или, перефразируя вопрос: как немодульный скрипт может динамически загружать модуль синхронно?

1 Ответ

2 голосов
/ 05 мая 2020

Подождите, пока не произойдет событие domcontentloaded в вашем файле index.html. В обратном вызове события импортируйте модуль, который вы хотите запускать всякий раз, когда событие запускается.

// app.js
export function start() {
  console.log('in module');
  console.log('DCL:2');
}
<!-- index.html -->
<script>
  (async () => {
    document.addEventListener('DOMContentLoaded', (event) => {
      const module = await import("./js/app.js");
      module.start();
      console.log('async done');
    });
  })();
</script>

Или, если вам не нужны никакие модули, и вы просто хотите, чтобы все загружалось один за другим. другой до того, как DOM будет отрисован, просто используйте традиционные теги блокировки рендеринга <script>.

<script src="./js/app.js"></script>
<script>
  console.log('module loaded');
</script>
...