Промисы и async/await

Тема дорожной карты · Frontend разработчик

Асинхронное программирование на JavaScript — это набор языковых паттернов и Web API, обрабатывающих операции, которые не завершаются немедленно (сетевые запросы, таймеры, файловый ввод-вывод, взаимодействия с пользователем), не блокируя главный поток и не замораживая интерфейс. Эволюция асинхронных паттернов JavaScript идёт от коллбэков (error-first function(err, data)) к цепочкам Promise (.then(), .catch(), .finally()) и к синтаксическому сахару async/await, который делает асинхронный код читаемым последовательно, продолжая исполняться неблокирующим образом в цикле событий. Комбинаторы Promise.all(), Promise.allSettled(), Promise.race() и Promise.any() эффективно обрабатывают несколько параллельных асинхронных операций, а AbortController с AbortSignal позволяет отменять незавершённые fetch-запросы. Владение асинхронными паттернами JavaScript критически важно для каждого frontend-разработчика, работающего с библиотеками получения данных React (React Query или SWR), поскольку понимание цепочек Promise и работы очереди микрозадач предотвращает скрытые баги в состояниях загрузки и гонках данных.

Как это работает

Промисы и async/await покрывает closures, hoisting, прототипные цепочки, event loop (microtasks vs macrotasks), модули (ESM import/export), iterators/generators, Symbol/Proxy/Reflect, GC, модель памяти runtime. Асинхронные паттерны: Promise.all/race/allSettled, AbortController для отмены, AsyncIterator + for await...of, Web Workers для параллелизма. Performance-примитивы: requestAnimationFrame, requestIdleCallback, IntersectionObserver.

Когда применять

Берите это после построения чего-то больше формы — closures объясняют, почему React-хуки ведут себя так; event loop объясняет, почему setTimeout срабатывает позже ожидаемого; AbortController нужен для отмены fetch, когда юзер уходит. Web Workers — только когда CPU-bound работа блокирует main thread (обработка изображений, парсинг большого JSON).

Типичные ошибки

Ловушки Промисы и async/await: closures над переменными цикла захватывают последнее значение (используйте let в цикле или forEach); утечки памяти от event-handler'ов, которые не сняли; over-engineering с Proxy/Reflect, когда хватит обычного объекта; race conditions в конкурентных promise (Promise.race — намеренно, не случайно); блокировка main thread синхронным тяжёлым compute.

Связанные понятия

Полезные ресурсы