Где сталкивался с Event Loop в JavaScript?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Event Loop в JavaScript
Event Loop — это ядро асинхронной модели JavaScript, которое управляет выполнением кода. С этим механизмом приходится сталкиваться постоянно при работе с таймерами, промисами, обработкой событий и асинхронными операциями в браузере и Node.js.
Где я сталкивался с Event Loop
По опыту, наиболее часто конкретные проблемы с Event Loop возникают в следующих ситуациях:
1. Асинхронные операции и задержки
При работе с setTimeout, setInterval и других асинхронных API браузера. Например, обработка очереди задач при загрузке данных с сервера:
console.log("1");
setTimeout(() => {
console.log("2");
}, 0);
Promise.resolve().then(() => {
console.log("3");
});
console.log("4");
// Порядок: 1, 4, 3, 2
2. Микротаски vs макротаски
В React компонентах часто нужно понимать, почему useEffect срабатывает в определённый момент. Промисы (микротаски) выполняются быстрее, чем setTimeout (макротаски):
function App() {
useEffect(() => {
// Микротаска
Promise.resolve().then(() => console.log("Promise"));
// Макротаска
setTimeout(() => console.log("Timeout"), 0);
}, []);
return <div>Example</div>;
}
// Promise выполнится РАНЬШЕ, чем Timeout
3. Блокировка Event Loop Сталкивался с ситуациями, когда сложные вычисления блокируют Event Loop и замораживают интерфейс. Например, синхронная обработка большого массива данных:
// ПЛОХО - блокирует Event Loop
const processLargeArray = (arr) => {
return arr.map(item => {
// Сложные вычисления
return heavyComputation(item);
});
};
// ХОРОШО - использование Web Workers или разбиение на батчи
const processBatch = async (arr, batchSize = 100) => {
const results = [];
for (let i = 0; i < arr.length; i += batchSize) {
const batch = arr.slice(i, i + batchSize);
results.push(...batch.map(heavyComputation));
// Даём Event Loop обработать события
await new Promise(resolve => setTimeout(resolve, 0));
}
return results;
};
4. Event Listeners и утечки памяти При работе с глобальными Event Listeners часто нужно следить за Event Loop, чтобы не создавать утечки памяти:
// В React компоненте
useEffect(() => {
const handleScroll = () => {
// Обработка скролла
};
window.addEventListener("scroll", handleScroll);
// ОБЯЗАТЕЛЬНО удалить слушатель
return () => window.removeEventListener("scroll", handleScroll);
}, []);
5. Обработка ошибок в асинхронном коде Ошибки в микротасках (Promise rejections) требуют специальной обработки в Event Loop:
// Необработанный Promise rejection
Promise.reject(new Error("Ошибка!")).catch(err => {
// Ловим ошибку из Event Loop
console.error("Caught:", err.message);
});
Как Event Loop работает
Основной цикл:
- Call Stack — выполняется синхронный код
- Микротаски — Promises, MutationObserver (выполняются ВСЕ перед следующей макротаской)
- Макротаски — setTimeout, setInterval, I/O (выполняется одна за раз)
- Render — перерисовка браузера (если нужна)
Практический пример из реальной разработки
При оптимизации производительности сложного списка в React:
function HeavyList({ items }) {
const [rendered, setRendered] = useState([]);
useEffect(() => {
// Разбиваем рендеринг на порции
const renderInBatches = async () => {
const batchSize = 50;
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
setRendered(prev => [...prev, ...batch]);
// Даём браузеру время на перерисовку
await new Promise(resolve => {
setTimeout(resolve, 0);
});
}
};
renderInBatches();
}, [items]);
return (
<div>
{rendered.map(item => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}
Понимание Event Loop критически важно для написания производительного и надёжного кода в JavaScript, особенно в современных фреймворках как React.