async/await
Тема дорожной карты · Node.js
Async/await — это синтаксический сахар поверх Promise, позволяющий писать асинхронный JavaScript-код так, будто он синхронный, что значительно улучшает читаемость серверных приложений на Node.js. Ключевое слово async помечает функцию как асинхронную, заставляя её неявно возвращать Promise, тогда как ключевое слово await приостанавливает выполнение внутри этой функции до тех пор, пока ожидаемый Promise не будет разрешён или отклонён. В цикле событий Node.js await возвращает управление среде выполнения, позволяя выполняться другим задачам, что делает код неблокирующим и подходящим для рабочих нагрузок с интенсивным I/O, таких как запросы к базе данных, вызовы fs.readFile() или HTTP-запросы. Обработка ошибок с async/await использует стандартные блоки try/catch вместо цепочек .catch(), что упрощает управление потоком выполнения в обработчиках маршрутов Express.js и серверных сервисах. Владение async/await необходимо для написания чистого, поддерживаемого асинхронного кода на Node.js без «callback hell» и глубоко вложенных цепочек Promise.
Как это работает
async/await — сердце Node: event loop libuv проходит фазы timers, pending I/O callbacks, idle/prepare, poll, check, close-callbacks. async/await — современный примитив; promises — механизм под капотом; callbacks — legacy. setImmediate запускается на следующей итерации; process.nextTick — до любого I/O, злоупотребление ломает loop. Worker threads (worker_threads) гонят JS параллельно; у них отдельные event loop, изолированная память, обмен сообщениями.
Когда применять
async/await — везде в новом коде; callbacks — для legacy или streams. Promise.all/allSettled — для параллельного I/O когда независимы. CPU-bound работа — в worker_threads или отдельный сервис; никогда не блокируйте main loop. AbortController — для отмены долгих операций. Профилируйте event-loop lag (perf_hooks.monitorEventLoopDelay) в production — устойчивый lag > 50ms = проблема.
Типичные ошибки
Ловушки async/await: забытый await → unhandled promise rejection (Node логирует warning, скоро будет crash); Promise.all падает на первом, когда хотели partial success (Promise.allSettled); глубокие then-цепочки там, где async/await читался бы линейно; setTimeout(0) для "yield в loop" (используйте setImmediate); рекурсия, растящая stack вместо возврата promise.