\n\n\n

Привет

\n \n\n\n```\n\n**Что происходит:**\n\n1. Браузер начинает парсить HTML\n2. Встречает `\n\n\n \n

Заголовок

\n\n```\n\n**Сценарий 2: async/defer скрипты**\n\n```html\n\n \n \n\n\n \n

Заголовок видит пользователь

\n\n```\n\n- **async** — загружается в фоне, выполняется в Event Loop (когда загрузится)\n- **defer** — загружается в фоне, выполняется в Event Loop (после парсинга)\n\n### Как это влияет на производительность\n\n**Плохо (FCP — First Contentful Paint долгий):**\n\n```html\n\n \n \n\n\n \n

Контент

\n\n```\n\n**Хорошо (FCP быстрый):**\n\n```html\n\n \n\n\n \n

Контент

\n \n \n\n```\n\n### Ренденеринг и Event Loop\n\n**После выполнения скрипта в Event Loop браузер:**\n\n1. Проверяет, нужно ли перерендерить\n2. Выполняет Layout (расчёт размеров)\n3. Выполняет Paint (рисование)\n4. Выполняет Composite (слои)\n\n**Если скрипт изменял DOM:**\n\n```javascript\nconst div = document.getElementById('box');\ndiv.style.backgroundColor = 'red';\n// Event Loop → Render (браузер перерисует div)\n```\n\n### Лучшие практики\n\n**1. Используй defer для основного JS:**\n```html\n\n```\n\n**2. Используй async только для независимых:**\n```html\n\n```\n\n**3. Минимизируй синхронный JS:**\n```javascript\n// Плохо: долгий синхронный код\nfunction heavyCalculation() {\n let sum = 0;\n for (let i = 0; i < 1000000000; i++) sum += i;\n return sum;\n}\n\n// Хорошо: разбей на части через Event Loop\nfunction* heavyCalculation() {\n let sum = 0;\n for (let i = 0; i < 1000000000; i++) {\n if (i % 1000000 === 0) yield sum;\n sum += i;\n }\n return sum;\n}\n```\n\n**4. Используй Web Workers для CPU-intensive:**\n```javascript\nconst worker = new Worker('/worker.js');\nworker.postMessage({ data: largeArray });\nworker.onmessage = (e) => {\n console.log('Результат из воркера (Event Loop не заблокирован):', e.data);\n};\n```\n\n### Итог\n\nПарсинг HTML и Event Loop **независимы**, но **синхронный JavaScript блокирует парсинг**. Используй `async` и `defer` для скриптов, чтобы парсинг продолжался параллельно, и пользователь быстрее видит контент.","dateCreated":"2026-04-02T22:21:09.921971","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как парсинг HTML связан с Event Loop?

1.7 Middle🔥 271 комментариев
#HTML и CSS

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Event Loop и парсинг HTML

Парсинг HTML происходит вне Event Loop, но синхронный JavaScript блокирует парсинг. Это критично для производительности.

Как работает парсинг

Браузер делает это последовательно:

  1. Получает HTML с сервера
  2. Парсит HTML (создаёт DOM)
  3. Встречает <script> — СТОП парсинг
  4. Выполняет скрипт (Event Loop обрабатывает JS)
  5. Возобновляет парсинг HTML
  6. Рендерит DOM (Paint, Layout)

Этот процесс не входит в Event Loop, но JavaScript в Event Loop может остановить парсинг.

Визуализация

HTML Processing (не Event Loop):
├─ Parse HTML
├─ Встречен <script>
│  └─ Execute JavaScript (Event Loop)
│     ├─ Микротаски (Promises, queueMicrotask)
│     └─ Макротаски (setTimeout, setInterval)
├─ Парсинг продолжается
├─ Построен DOM
└─ Отрендерить страницу

Проблема: Блокирующие скрипты

<html>
<head>
  <script src="/heavy.js"></script>
</head>
<body>
  <h1>Привет</h1>
  <!-- Пока /heavy.js загружается и выполняется —
       парсинг СТОИТ, пользователь видит белый экран -->
</body>
</html>

Что происходит:

  1. Браузер начинает парсить HTML
  2. Встречает <script src="/heavy.js">
  3. Парсинг HTML СТОИТ
  4. Загружается heavy.js (может занять 5 секунд)
  5. Выполняется в Event Loop (может занять 2 секунды)
  6. Только потом браузер видит <body> и <h1>
  7. Белый экран 7+ секунд

Event Loop: макротаски vs микротаски

В Event Loop есть приоритет:

While (Event Loop жив) {
  1. Выполни макротаску (setTimeout, setInterval)
  2. Выполни ВСЕ микротаски (Promises, queueMicrotask)
  3. Перерендер страницы (если нужно)
  4. Повтори
}

Пример:

console.log('1. Синхронный код');

setTimeout(() => {
  console.log('2. Макротаска (setTimeout)');
}, 0);

Promise.resolve()
  .then(() => {
    console.log('3. Микротаска (Promise)');
  });

console.log('4. Ещё синхронный');

// Порядок выполнения:
// 1. Синхронный код
// 4. Ещё синхронный
// 3. Микротаска (Promise)
// 2. Макротаска (setTimeout)

Как парсинг HTML и Event Loop взаимодействуют

Сценарий 1: Тяжёлый скрипт в head

<head>
  <script>
    // Этот код выполнится в Event Loop
    let sum = 0;
    for (let i = 0; i < 1000000000; i++) {
      sum += i;
    }
  </script>
</head>
<body>
  <!-- Пока вычисляется sum, парсинг HTML ЖДЁТ -->
  <h1>Заголовок</h1>
</body>

Сценарий 2: async/defer скрипты

<head>
  <script async src="/analytics.js"></script>
  <script defer src="/app.js"></script>
</head>
<body>
  <!-- Парсинг HTML ПРОДОЛЖАЕТСЯ, скрипты загружаются параллельно -->
  <h1>Заголовок видит пользователь</h1>
</body>
  • async — загружается в фоне, выполняется в Event Loop (когда загрузится)
  • defer — загружается в фоне, выполняется в Event Loop (после парсинга)

Как это влияет на производительность

Плохо (FCP — First Contentful Paint долгий):

<head>
  <script src="/vendor.js"></script> <!-- 3 сек -->
  <script src="/app.js"></script> <!-- 2 сек -->
</head>
<body>
  <!-- FCP = 5 сек (белый экран) -->
  <h1>Контент</h1>
</body>

Хорошо (FCP быстрый):

<head>
  <script async src="/analytics.js"></script>
</head>
<body>
  <!-- FCP = ~0.2 сек (контент видит пользователь) -->
  <h1>Контент</h1>
  <script defer src="/vendor.js"></script>
  <script defer src="/app.js"></script>
</body>

Ренденеринг и Event Loop

После выполнения скрипта в Event Loop браузер:

  1. Проверяет, нужно ли перерендерить
  2. Выполняет Layout (расчёт размеров)
  3. Выполняет Paint (рисование)
  4. Выполняет Composite (слои)

Если скрипт изменял DOM:

const div = document.getElementById('box');
div.style.backgroundColor = 'red';
// Event Loop → Render (браузер перерисует div)

Лучшие практики

1. Используй defer для основного JS:

<script defer src="/app.js"></script>

2. Используй async только для независимых:

<script async src="/gtag.js"></script>

3. Минимизируй синхронный JS:

// Плохо: долгий синхронный код
function heavyCalculation() {
  let sum = 0;
  for (let i = 0; i < 1000000000; i++) sum += i;
  return sum;
}

// Хорошо: разбей на части через Event Loop
function* heavyCalculation() {
  let sum = 0;
  for (let i = 0; i < 1000000000; i++) {
    if (i % 1000000 === 0) yield sum;
    sum += i;
  }
  return sum;
}

4. Используй Web Workers для CPU-intensive:

const worker = new Worker('/worker.js');
worker.postMessage({ data: largeArray });
worker.onmessage = (e) => {
  console.log('Результат из воркера (Event Loop не заблокирован):', e.data);
};

Итог

Парсинг HTML и Event Loop независимы, но синхронный JavaScript блокирует парсинг. Используй async и defer для скриптов, чтобы парсинг продолжался параллельно, и пользователь быстрее видит контент.