Приведи примеры создания макрозадач
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Создание макрозадач в JavaScript: полный обзор
Макрозадачи (macrotasks) — это задачи, которые выполняются в основном потоке выполнения JavaScript после завершения текущего синхронного кода и перед следующей итерацией цикла событий. Вот основные способы их создания с подробными примерами.
1. setTimeout() и setInterval() — классические макрозадачи
Наиболее распространённые API для создания макрозадач. Они помещают колбэк в очередь макрозадач после указанной задержки.
// Пример с setTimeout
console.log('Старт синхронного кода');
setTimeout(() => {
console.log('Макрозадача из setTimeout выполнилась');
}, 1000);
setTimeout(() => {
console.log('Макрозадача с нулевой задержкой');
}, 0);
console.log('Конец синхронного кода');
// Вывод:
// Старт синхронного кода
// Конец синхронного кода
// Макрозадача с нулевой задержкой
// Макрозадача из setTimeout выполнилась
// Пример с setInterval
let counter = 0;
const intervalId = setInterval(() => {
counter++;
console.log(`Интервал выполнен ${counter} раз`);
if (counter >= 3) {
clearInterval(intervalId);
console.log('Интервал остановлен');
}
}, 500);
// setInterval создаёт новую макрозадачу каждые 500 мс
2. setImmediate() — Node.js специфика
Доступен только в среде Node.js, планирует выполнение колбэка сразу после завершения текущего цикла событий.
// Пример в Node.js
console.log('Начало выполнения');
setImmediate(() => {
console.log('setImmediate выполнен');
});
setTimeout(() => {
console.log('setTimeout с нулевой задержкой');
}, 0);
console.log('Конец синхронного кода');
// Возможный вывод:
// Начало выполнения
// Конец синхронного кода
// setTimeout с нулевой задержкой
// setImmediate выполнен
// Порядок может варьироваться в зависимости от фазы цикла событий
3. Обработчики событий — пользовательские взаимодействия
Любые события DOM (клики, нажатия клавиш, загрузка ресурсов) создают макрозадачи.
// Пример с обработчиком клика
document.getElementById('myButton').addEventListener('click', () => {
console.log('Обработчик клика — это макрозадача');
});
// События загрузки
window.addEventListener('load', () => {
console.log('Страница полностью загружена — макрозадача');
});
// События таймера requestAnimationFrame (хотя имеет особый статус)
requestAnimationFrame(() => {
console.log('requestAnimationFrame — выполняется перед ререндером');
});
4. MessageChannel — продвинутое создание макрозадач
Позволяет явно создать макрозадачу с более высоким приоритетом, чем setTimeout(..., 0).
// Создание канала для передачи сообщений
const channel = new MessageChannel();
const port = channel.port2;
channel.port1.onmessage = () => {
console.log('Макрозадача через MessageChannel выполнена');
};
console.log('Перед отправкой сообщения');
port.postMessage(null);
console.log('После отправки сообщения');
// Вывод:
// Перед отправкой сообщения
// После отправки сообщения
// Макрозадача через MessageChannel выполнена
5. Динамический импорт модулей — import()
Динамический импорт также создаёт макрозадачу для загрузки и выполнения модуля.
// Пример динамического импорта
console.log('Начинаем загрузку модуля');
import('./myModule.js')
.then(module => {
console.log('Модуль загружен — макрозадача выполнена');
module.someFunction();
})
.catch(error => {
console.error('Ошибка загрузки модуля:', error);
});
console.log('Синхронный код продолжает выполняться');
6. queueMicrotask() vs макрозадачи — важное отличие
Для контраста покажу разницу между микрозадачами и макрозадачами:
console.log('Скрипт начался');
// Макрозадача
setTimeout(() => {
console.log('Макрозадача из setTimeout');
}, 0);
// Микрозадача
Promise.resolve().then(() => {
console.log('Микрозадача из Promise');
});
// Ещё одна микрозадача
queueMicrotask(() => {
console.log('Микрозадача из queueMicrotask');
});
console.log('Скрипт завершился');
// Вывод:
// Скрипт начался
// Скрипт завершился
// Микрозадача из Promise
// Микрозадача из queueMicrotask
// Макрозадача из setTimeout
Ключевые особенности макрозадач:
- Выполняются после микрозадач — приоритет микрозадач выше
- Не блокируют основной поток — браузер может рендерить между макрозадачами
- Могут быть отменены —
clearTimeout(),clearInterval() - Имеют минимальную задержку — обычно 4-10 мс в браузерах даже при
setTimeout(..., 0) - Подвержены throttle — в неактивных вкладках таймеры замедляются
Практический пример с анимацией:
// Поэтапная анимация через макрозадачи
function animateElement(element, duration) {
const startTime = Date.now();
function updateAnimation() {
const elapsed = Date.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
// Обновляем стиль элемента
element.style.transform = `translateX(${progress * 200}px)`;
if (progress < 1) {
// Создаём новую макрозадачу для следующего кадра
setTimeout(updateAnimation, 16); // ~60 FPS
}
}
// Запускаем первую макрозадачу
setTimeout(updateAnimation, 0);
}
// Использование
const box = document.getElementById('animatedBox');
animateElement(box, 1000); // Анимация на 1 секунду
Понимание работы макрозадач критически важно для написания производительного и отзывчивого JavaScript-кода, особенно при работе с анимациями, обработкой пользовательского ввода и управлением состоянием приложения.