Асинхронность — одна из главных особенностей JavaScript, которая часто вызывает затруднения у начинающих. Понять её — значит понять, как JS работает внутри.

Почему JS асинхронный

JavaScript — однопоточный язык: одновременно выполняется только одна операция. Если бы запрос к серверу блокировал поток — браузер зависал бы на время ожидания. Решение: асинхронные операции (сетевые запросы, таймеры, файловый ввод-вывод) не блокируют поток, а возвращают управление и уведомляют о завершении через callback.

Event Loop

Event loop — механизм, координирующий выполнение кода, очереди задач и Web APIs. Call stack выполняет синхронный код. Когда асинхронная операция завершается — callback попадает в Task Queue. Event loop переносит задачи из очереди в Call Stack, когда стек пуст.

// event_loop.js
console.log('1');           // синхронно

setTimeout(() => {
  console.log('2');         // async — в очередь
}, 0);

console.log('3');           // синхронно

// Вывод: 1, 3, 2

Callback Hell и проблемы

Колбэки работают, но при вложенности создают «пирамиду ада» — код, который сложно читать и отлаживать.

Promises: обещания

// promises.js
// Создание Promise
const fetchUser = (id) => new Promise((resolve, reject) => {
  if (id > 0) resolve({ id, name: 'Alice' });
  else reject(new Error('Неверный ID'));
});

// Цепочка .then().catch()
      Асинхронный JavaScript event loop
      
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_await.js
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');
JavaScript промисы и async await