Асинхронный JavaScript: ключевые конструкции для прохождения интервью

Раздел: Программирование -> Подготовка к собеседованию

Основные асинхронные механизмы

Почему в JavaScript требуется асинхронное выполнение?

JavaScript выполняется в одном потоке, использующем Event Loop. Долгие операции (запросы к серверу, таймеры, чтение файлов) блокировали бы поток, поэтому они выполняются асинхронно. Базовые подходы: колбэки, Promise, async/await.

Как реализовать асинхронность с помощью колбэков?

Колбэк - функция, переданная в другую функцию и вызываемая после завершения асинхронной операции.

setTimeout(() => { console.log('Выполнено'); }, 1000);

Js вопросы (вопросы по javascript для собеседования)

Цель: обработка результата после задержки. Используется в старых API (например, fs.readFile в Node.js).

Проблема: Callback hell - вложенные колбэки усложняют читаемость. Также трудно обрабатывать ошибки централизованно. Пример ошибки: забыть проверить первый аргумент (err) приводит к необработанным исключениям.

Как упростить асинхронный код с Promise?

Promise - объект, представляющий результат асинхронной операции. Позволяет цепочки .then() и .catch().

fetch('/data').then(response => response.json()).then(data => console.log(data)).catch(error => console.error(error));

Цель: избежать вложенности, улучшить обработку ошибок. Используется в современных API.

Проблема: Если забыть return в .then(), цепочка нарушается. Необработанные исключения в Promise (без .catch) приводят к игнорированию ошибок. Также сложно отменить Promise.

Как сделать асинхронный код похожим на синхронный с async/await?

async/await - синтаксический сахар над Promise. Функция с async возвращает Promise, await приостанавливает выполнение до разрешения.

async function getData() { try { const response = await fetch('/data'); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } }

Цель: линейный код без цепочек, упрощение отладки. Поддерживает try/catch.

Проблема: await блокирует выполнение внутри async функции, но не блокирует поток. Частая ошибка - забыть try/catch или использовать await в цикле последовательно там, где можно параллельно (Promise.all). Также async функции всегда возвращают Promise, что может быть неочевидно.

Расширенные примеры асинхронных паттернов

Пример колбэка с обработкой ошибки и демонстрация callback hell:

Пример
// Пример колбэка с проверкой ошибки
function loadUser(id, callback) {
  setTimeout(() => {
    if (id <= 0) {
      callback(new Error('Invalid id'), null);
    } else {
      callback(null, { id, name: 'User' + id });
    }
  }, 100);
}
// Использование
loadUser(1, (err, user) => {
  if (err) return console.error(err);
  console.log(user.name);
});
// Результат: User1

Пример цепочки Promise с параллельным выполнением:

Пример
const urls = ['/api/1', '/api/2', '/api/3'];
Promise.all(urls.map(url => fetch(url).then(res => res.json())))
  .then(results => console.log(results))
  .catch(err => console.error('Ошибка:', err));
// Результат: [данные1, данные2, данные3]

Пример async/await с параллельным выполнением через Promise.all:

Пример
async function fetchAllUrls(urls) {
  try {
    const promises = urls.map(url => fetch(url).then(res => res.json()));
    const results = await Promise.all(promises);
    console.log(results);
  } catch (err) {
    console.error('Ошибка:', err);
  }
}
// Результат: [данные1, данные2, данные3]

Пример обработки ошибок в Promise с использованием finally:

Пример
fetch('/data')
  .then(data => data.json())
  .catch(err => console.error('Fetch error:', err))
  .finally(() => console.log('Завершено'));
// Результат: 'Завершено' появляется независимо от успеха/ошибки

Пример использования Promise.race для временной защиты:

Пример
const timeout = new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 5000));
const request = fetch('/slow-endpoint');
Promise.race([request, timeout])
  .then(response => console.log(response))
  .catch(err => console.error(err.message));
// Если запрос дольше 5 секунд, получим 'Timeout'

Пример генератора (устаревший, но возможный подход) с использованием co:

Пример
// Для демонстрации, не рекомендуется в современном коде
function* gen() {
  const data = yield fetch('/data').then(r => r.json());
  console.log(data);
}
// Используется библиотека co или ручная обертка
// Результат: требует внешнего выполнения

Вопросы по JavaScript для собеседования - comments

En
Js вопросы (javascript)