Callbacks
Тема дорожной карты · Node.js
Колбэки — это исходный паттерн асинхронного программирования в Node.js, при котором функция передаётся в качестве аргумента и вызывается средой выполнения JavaScript после завершения асинхронной операции. Node.js стандартизировал соглашение об ошибке в первом аргументе (error-first callback): первый аргумент каждого колбэка зарезервирован для объекта Error (или null при успехе), что вынуждает разработчиков явно обрабатывать ошибки перед обращением к результату. Встроенные модули fs, http и dns используют колбэки — например, fs.readFile(path, callback) уведомляет цикл событий о готовности файла без блокировки других операций. Глубоко вложенные колбэки, часто называемые «callback hell», усложняют чтение и поддержку кода; эта проблема привела к появлению Promise и async/await как более высокоуровневых асинхронных абстракций в современной серверной разработке на Node.js. Хотя новые API Node.js предпочитают Promise, понимание колбэков по-прежнему важно, поскольку значительная часть экосистемы npm и внутреннего кода Node.js опирается на паттерн колбэков.
Как это работает
Callbacks — сердце 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 = проблема.
Типичные ошибки
Ловушки Callbacks: забытый await → unhandled promise rejection (Node логирует warning, скоро будет crash); Promise.all падает на первом, когда хотели partial success (Promise.allSettled); глубокие then-цепочки там, где async/await читался бы линейно; setTimeout(0) для "yield в loop" (используйте setImmediate); рекурсия, растящая stack вместо возврата promise.