← Назад к вопросам

Какие знаешь виды задач в браузере?

1.7 Middle🔥 182 комментариев
#Soft Skills и рабочие процессы

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

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

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

Типы задач (Tasks) в браузере

В современных браузерах выполнение кода организовано через систему задач (tasks) и микрозадач (microtasks), которые управляются циклом событий (Event Loop). Это фундаментальная модель асинхронности, обеспечивающая отзывчивость интерфейса. Вот основные виды задач:

1. Макрозадачи (Macrotasks / Tasks)

Это основные единицы работы, которые планируются в очередь задач (Task Queue). Каждая макрозадача выполняется полностью от начала до конца, и между ними браузер может выполнять рендеринг. К ним относятся:

  • Скрипты (Script execution): Запуск основного скрипта (<script src="...">), обработчики событий, загруженные динамически.
  • События UI (UI Events): click, scroll, resize, input.
  • Сетевые события (Network Events): Загрузка ресурсов (изображений, скриптов), ответы fetch (но осторожно, промисы из fetch — это микрозадачи!).
  • Таймеры (Timers): Колбэки из setTimeout и setInterval.
  • requestAnimationFrame (rAF): Хотя технически это не совсем макрозадача в классической очереди, его колбэк выполняется в фазе рендеринга, что делает его похожим на высокоприоритетную задачу для анимаций.
  • Операции ввода-вывода (I/O): Например, события из WebSockets или localStorage.
  • postMessage и MessageChannel.

2. Микрозадачи (Microtasks)

Очередь микрозадач (Microtask Queue) имеет высший приоритет. Она очищается полностью после каждой макрозадачи (или после некоторых других операций) до того, как цикл событий перейдет к рендерингу или следующей макрозадаче. Это ключевая особенность! К микрозадачам относятся:

  • Колбэки промисов (Promise callbacks): .then(), .catch(), .finally().
  • async/await: По сути, await "разворачивается" в цепочку промисов.
  • queueMicrotask(): Прямой API для добавления функции в очередь микрозадач.
  • Мутационные наблюдатели (MutationObserver): Колбэки срабатывают при изменениях DOM.
  • Часть lifecycle колбэков в веб-компонентах.

3. Задачи отложенного рендеринга (Animation Frame Tasks)

Особая категория — задачи, связанные с подготовкой кадра анимации:

  • requestAnimationFrame: Его колбэк выполняется непосредственно перед этапом Layout и Paint в цикле событий. Это идеальное место для обновления анимаций, так как гарантирует синхронизацию с частотой обновления экрана.

Порядок выполнения (Event Loop)

console.log('1. Старт макрозадачи (скрипт)'); // Макрозадача

setTimeout(() => console.log('7. Макрозадача: таймер'), 0); // Макрозадача

Promise.resolve()
    .then(() => console.log('4. Микрозадача: промис 1')) // Микрозадача
    .then(() => console.log('6. Микрозадача: промис 2')); // Микрозадача

queueMicrotask(() => console.log('5. Микрозадача: queueMicrotask')); // Микрозадача

console.log('2. Синхронный код'); // Все еще внутри первой макрозадачи

requestAnimationFrame(() => console.log('Анимация! (зависит от фазы рендеринга)')); // ~Макрозадача rAF

// Имитация клика (еще одна макрозадача)
button.addEventListener('click', () => {
    console.log('Новая макрозадача: событие клика');
});

console.log('3. Конец первой макрозадачи');

Вывод и объяснение:

1. Старт макрозадачи (скрипт)
2. Синхронный код
3. Конец первой макрозадачи
4. Микрозадача: промис 1
5. Микрозадача: queueMicrotask
6. Микрозадача: промис 2
7. Макрозадача: таймер
Анимация! (зависит от фазы рендеринга)
  1. Выполняется первая макрозадача (основной скрипт целиком).
  2. Синхронный код (console.log) выполняется немедленно.
  3. setTimeout планирует свою колбэк-функцию как новую макрозадачу.
  4. Промисы и queueMicrotask добавляют свои колбэки в очередь микрозадач.
  5. После завершения всей текущей макрозадачи (кода скрипта), Event Loop проверяет очередь микрозадач.
  6. Вся очередь микрозадач опустошается последовательно (пункты 4, 5, 6).
  7. Только после этого браузер при необходимости выполняет рендеринг (и колбэк requestAnimationFrame, если он есть).
  8. Затем берется следующая макрозадача из очереди (колбэк setTimeout).

Важные нюансы и практическое значение

  • Блокирующий код — это длительная синхронная операция внутри макрозадачи. Она блокирует не только рендеринг, но и обработку всех других задач, включая микрозадачи.
  • Рендеринг (Layout/Paint) происходит между макрозадачами, но только если очередь микрозадач пуста и если есть необходимость (изменился DOM, стили и т.д.).
  • Рекурсивное создание микрозадач может заблокировать поток, так как Event Loop будет пытаться очистить бесконечную очередь микрозадач и не перейдет к следующей макрозадаче или рендерингу.
    function loopMicrotasks() {
        Promise.resolve().then(loopMicrotasks); // Блокирующий бесконечный цикл!
    }
    

Понимание этих видов задач критически важно для:

  • Оптимизации производительности и предотвращения задержек (lag).
  • Правильной работы анимаций (использовать requestAnimationFrame, а не setTimeout).
  • Предсказуемого порядка выполнения асинхронного кода (промисы vs таймеры).
  • Отладки сложного асинхронного потока.

Эта модель гарантирует, что высокоприоритетные обновления (например, через промисы) выполняются как можно скорее, а браузер сохраняет отзывчивость для пользовательского ввода.

Какие знаешь виды задач в браузере? | PrepBro