Асинхронность — одна из главных особенностей JavaScript, которая часто вызывает затруднения у начинающих. Понять её — значит понять, как JS работает внутри.
Почему JS асинхронный
JavaScript — однопоточный язык: одновременно выполняется только одна операция. Если бы запрос к серверу блокировал поток — браузер зависал бы на время ожидания. Решение: асинхронные операции (сетевые запросы, таймеры, файловый ввод-вывод) не блокируют поток, а возвращают управление и уведомляют о завершении через callback.
Event Loop
Event loop — механизм, координирующий выполнение кода, очереди задач и Web APIs. Call stack выполняет синхронный код. Когда асинхронная операция завершается — callback попадает в Task Queue. Event loop переносит задачи из очереди в Call Stack, когда стек пуст.
console.log('1'); // синхронно setTimeout(() => { console.log('2'); // async — в очередь }, 0); console.log('3'); // синхронно // Вывод: 1, 3, 2
Callback Hell и проблемы
Колбэки работают, но при вложенности создают «пирамиду ада» — код, который сложно читать и отлаживать.
Promises: обещания
// Создание Promise const fetchUser = (id) => new Promise((resolve, reject) => { if (id > 0) resolve({ id, name: 'Alice' }); else reject(new Error('Неверный ID')); }); // Цепочка .then().catch()![]()
fetchUser(1) .then(user => console.log(user.name)) .catch(err => console.error(err.message)); // Promise.all — параллельно const [u1, u2] = await Promise.all([fetchUser(1), fetchUser(2)]);
// async/await — синтаксический сахар над Promise
async/await не делает код синхронным — он делает его похожим на синхронный. Под капотом всё те же Promise. Функция с async всегда возвращает Promise. await приостанавливает выполнение текущей async-функции до разрешения Promise.
async/await на практике
async function getGitHubUser(username) { try { const response = await fetch(`https://api.github.com/users/${username}`); if (!response.ok) { throw new Error(`HTTP error: ${response.status}`); } const data = await response.json(); return data; } catch (error) { console.error('Ошибка:', error.message); } } // Вызов const user = await getGitHubUser('torvalds');