Мок-собеседование по Node.js
Мок-собеседование по Node.js для бэкенд- и фулстек-разработчиков, которые готовятся на позицию junior, middle или senior. ИИ-интервьюер спрашивает про event loop, стримы, обработку async-ошибок, масштабирование, производительность и безопасность, а вы отвечаете вслух, как на реальном созвоне. Выберите уровень или загрузите резюме либо описание вакансии и получите отчёт с оценками по технической точности, полноте и ясности.
О чём спрашивают на собеседовании по Node.js
Event loop и libuv
Фазы event loop (timers, poll, check, close), где выполняются process.nextTick и микротаски промисов и какую работу libuv отдаёт в пул потоков (fs, dns.lookup, crypto, zlib).
Стримы и backpressure
Readable, Writable, Duplex и Transform, highWaterMark, что делать, когда write() вернул false, и почему stream.pipeline лучше ручных цепочек .pipe() для обработки ошибок и освобождения ресурсов.
Асинхронность и обработка ошибок
Колбэки, промисы и async/await, Promise.all против allSettled, отмена через AbortController и что делать с unhandledRejection и uncaughtException.
Worker threads, cluster и масштабирование
Когда CPU-задачам нужны worker_threads, как cluster или process manager использует все ядра и почему в продакшене обычно масштабируются stateless-контейнерами за балансировщиком.
Производительность и утечки памяти
Как заметить заблокированный event loop, профилирование через --cpu-prof и Chrome DevTools, разбор heap snapshot и типичные источники утечек: глобальные кэши, листенеры и замыкания, которые никогда не освобождаются.
Безопасность
Инъекции и prototype pollution, валидация ввода, хранение секретов, риски зависимостей и supply chain (npm audit, lock-файлы), rate limiting и безопасные HTTP-заголовки.
HTTP, API и фреймворки
Middleware в Express, плагины и валидация схем в Fastify, модули и DI в NestJS, REST против GraphQL, graceful shutdown и keep-alive соединения.
Тестирование
Юнит- и интеграционные тесты на node:test, Jest или Vitest, моки таймеров и сетевых запросов, тесты с реальной БД в контейнерах и как держать тесты быстрыми и детерминированными.
Вопросы на собеседовании по Node.js по уровням
Junior
Node.js выполняет JavaScript в одном потоке. Как он обрабатывает тысячи одновременных запросов?
Что должно быть в сильном ответе:JavaScript выполняется в одном потоке, но I/O неблокирующий: сокеты Node отдаёт ОС (epoll, kqueue, IOCP), а часть операций, например работу с файловой системой, в пул потоков libuv. Когда операция завершается, колбэк встаёт в очередь, и event loop его выполняет. Для I/O-нагрузки это работает отлично, но одна долгая CPU-задача блокирует все остальные запросы.
Чем отличаются process.nextTick, setImmediate и setTimeout(fn, 0)?
Что должно быть в сильном ответе:Колбэки process.nextTick выполняются сразу после текущей операции, раньше микротасок промисов и до продолжения event loop. setTimeout(fn, 0) срабатывает в фазе timers минимум через 1 мс, а setImmediate в фазе check сразу после poll. Внутри I/O-колбэка setImmediate всегда сработает раньше таймаута, а в основном модуле порядок не гарантирован. Рекурсивный nextTick может «заморить» I/O.
Чем отличаются CommonJS и ES-модули в Node.js?
Что должно быть в сильном ответе:CommonJS использует require и module.exports, загружается синхронно и используется по умолчанию для .js-файлов без "type": "module". ES-модули используют import/export, статически анализируются, поддерживают top-level await и включаются через .mjs или "type": "module". В ESM по умолчанию нет __dirname и require (вместо них import.meta.dirname или import.meta.url), а свежие версии Node умеют делать require() синхронных ES-модулей.
Как обрабатывать ошибки в колбэках, промисах и async/await?
Что должно быть в сильном ответе:Колбэки в Node построены по принципу error-first, поэтому сначала проверяете аргумент err, а потом результат. У промисов есть .catch, а с async/await оборачиваете await в try/catch или даёте ошибке подняться до централизованного обработчика. Забытый await или отсутствующий catch приводит к unhandled rejection, который с Node 15 по умолчанию роняет процесс.
Что такое middleware в Express и почему важен их порядок?
Что должно быть в сильном ответе:Middleware это функция (req, res, next), которая выполняется в порядке регистрации и может изменить запрос, завершить ответ или вызвать next(), чтобы передать управление дальше. Порядок важен: парсеры тела и авторизация должны стоять до роутов, а обработчик ошибок с четырьмя аргументами (err, req, res, next) идёт последним. В Express 5 отклонённые промисы из async-обработчиков автоматически попадают в обработчик ошибок.
Middle
Объясните стримы и backpressure. Что будет, если игнорировать backpressure?
Что должно быть в сильном ответе:Стримы обрабатывают данные по частям, а не грузят всё в память. Backpressure это сигнал, что потребитель медленнее источника: write() возвращает false, когда буфер превысил highWaterMark, и источник должен ждать события drain. Если это игнорировать, данные копятся в памяти, и процессу может не хватить heap. stream.pipeline (или его версия на промисах) учитывает backpressure, пробрасывает ошибки и закрывает все стримы при сбое.
Сравните Promise.all, Promise.allSettled, Promise.race и Promise.any. Когда что использовать?
Что должно быть в сильном ответе:Promise.all резолвится, когда все успешны, и отклоняется на первой ошибке, поэтому подходит, когда нужен каждый результат. allSettled ждёт все и возвращает статус каждого, это удобно для пакетных задач, где частичный сбой допустим. race завершается первым завершившимся промисом, обычно для таймаутов, а any возвращает первый успех и падает, только когда упали все. Ни один из них не отменяет оставшуюся работу, для настоящей отмены передают AbortSignal.
Что может заблокировать event loop и как это обнаружить и исправить?
Что должно быть в сильном ответе:Блокирует синхронная CPU-работа: тяжёлые циклы, JSON.parse или stringify больших данных, синхронные вызовы fs или crypto и катастрофический backtracking в регулярках. Обнаруживают по метрике задержки event loop (perf_hooks.monitorEventLoopDelay), через APM или CPU-профиль. Исправляют выносом CPU-работы в worker threads или отдельный сервис, разбиением на части, стримингом больших данных и асинхронными API.
Как найти и исправить утечку памяти в Node.js-сервисе?
Что должно быть в сильном ответе:Сначала убедиться, что это утечка: heap стабильно растёт между циклами GC при постоянной нагрузке, а не выходит на плато. Дальше снять два-три heap snapshot с интервалом (через --inspect, DevTools или --heapsnapshot-signal) и сравнить, какие объекты растут и что их удерживает. Типичные причины: неограниченные кэши или Map в памяти, листенеры, которые не снимаются, замыкания с большими объектами и неочищенные таймеры. Исправление: ограничить кэш или добавить TTL, снимать листенеры и проверить нагрузочным тестом.
Как реализовать graceful shutdown для HTTP-сервиса?
Что должно быть в сильном ответе:По SIGTERM перестаёте принимать новые соединения через server.close(), помечаете сервис как not ready, чтобы балансировщик перестал слать трафик, и даёте завершиться текущим запросам. Затем закрываете простаивающие keep-alive соединения, дочитываете очереди и закрываете пулы БД и другие клиенты. Жёсткий таймаут принудительно завершает процесс, если что-то зависло, чтобы оркестратор не убивал его SIGKILL посреди запроса.
Senior
Когда использовать worker_threads, cluster, child_process, а когда просто больше инстансов?
Что должно быть в сильном ответе:worker_threads выполняют JavaScript параллельно в одном процессе с возможностью общей памяти (SharedArrayBuffer, transferable-объекты) и подходят для CPU-задач вроде обработки изображений или парсинга, обычно через пул. cluster форкает процессы с общим портом, чтобы задействовать все ядра, но в контейнерах проще один процесс на контейнер и горизонтальное масштабирование. child_process нужен для запуска внешних программ или изоляции рискованной работы. Выбор зависит от того, что узкое место: CPU, изоляция или пропускная способность.
p99 задержки вашего Node.js API в продакшене резко выросла, а CPU в норме. Как будете разбираться?
Что должно быть в сильном ответе:Сначала посмотрю на задержку event loop и паузы GC, потом на внешние вызовы через distributed tracing: не замедлились ли БД, кэш или сторонний API. Другие частые причины: исчерпанный пул соединений, забитый пул потоков libuv (по умолчанию 4) из-за fs, dns.lookup или crypto и отсутствие таймаутов, из-за чего запросы стоят в очереди за медленными. Сопоставлю с последними деплоями и трафиком, воспроизведу под нагрузкой и подтвержу фикс метриками.
Какая у вас стратегия по unhandledRejection и uncaughtException в продакшене?
Что должно быть в сильном ответе:После необработанного исключения состояние процесса неизвестно, поэтому безопасно залогировать ошибку с контекстом, сбросить логи и метрики и выйти с ненулевым кодом, чтобы супервизор перезапустил процесс. Попытка работать дальше грозит испорченным состоянием и утечкой ресурсов. Unhandled rejection в современном Node и так роняет процесс, а настоящее решение в том, чтобы их не допускать: корректные await, централизованная обработка ошибок и линт-правила вроде no-floating-promises.
Как пробросить контекст запроса, например trace ID, через все async-вызовы без ручной передачи?
Что должно быть в сильном ответе:Через AsyncLocalStorage из node:async_hooks: в middleware запускаете хранилище на каждый запрос через als.run(), и любой код в этой async-цепочке может его прочитать, например логгер. На этом построены request-scoped логирование и трейсинг в OpenTelemetry и фреймворках вроде NestJS. Хранилище стоит держать маленьким, не превращать в скрытый DI и помнить, что контекст может теряться в некоторых библиотеках на собственных колбэках.
Как защитить Node.js API и его зависимости?
Что должно быть в сильном ответе:На уровне кода: валидация ввода схемами, параметризованные запросы, защита от prototype pollution при слиянии пользовательских объектов, security-заголовки, rate limiting и нормальная аутентификация. Для supply chain: коммитить lock-файл, ставить через npm ci, гонять npm audit или сканер в CI, минимизировать зависимости и осторожно относиться к install-скриптам. В рантайме: запуск не от root, секреты вне кода и логов, поддерживаемая LTS-версия и при необходимости permission model Node, чтобы ограничить доступ к fs или дочерним процессам.
Как проходит мок-собеседование по Node.js
- Выберите Node.js (и другие технологии из своего стека), свой уровень и язык собеседования: украинский, английский или русский. Или загрузите резюме и описание вакансии.
- Отвечайте на каждый вопрос голосом, как на настоящем собеседовании.
- Получите оценку каждого ответа по точности, полноте и понятности и отчёт со слабыми местами.
Как отвечать на вопросы по Node.js вслух
- →В вопросах про event loop называйте фазы по порядку (timers, pending callbacks, poll, check, close) и говорите, где место nextTick и микротасок промисов: чёткая последовательность звучит увереннее, чем размытое «оно асинхронное».
- →Привязывайте каждое понятие к последствию в продакшене: заблокированный event loop значит рост задержки для всех пользователей, проигнорированный backpressure значит рост памяти, unhandled rejection значит упавший процесс.
- →На вопрос «как бы вы дебажили X» идите по шагам: какую метрику смотрите первой, какой инструмент берёте (CPU-профиль, heap snapshot, трейсинг) и как проверяете, что фикс сработал.
- →Называйте конкретные API вместо описаний: stream.pipeline, AbortController, AsyncLocalStorage, worker_threads, server.close(). Это в паре слов показывает практический опыт.
- →В вопросах про фреймворки начните с механизма Node.js, а потом скажите, как его оборачивает Express, Fastify или NestJS: тогда ответ работает, даже если интервьюер имеет в виду другой фреймворк.
Частые вопросы
Нужно ли писать код во время мок-собеседования по Node.js?
Нет. Редактора для live coding нет: ИИ задаёт устные вопросы, а вы отвечаете голосом, объясняя концепции, компромиссы и как бы решили задачу. Так тренируется та часть собеседования, где нужно внятно рассказать про внутреннее устройство Node.js и архитектурные решения.
Можно ли совместить Node.js с TypeScript, PostgreSQL или другими технологиями?
Да. При выборе технологий можно указать несколько, например Node.js, TypeScript и PostgreSQL, и вопросы будут смешаны, как на обычном бэкенд-собеседовании. Также можно загрузить резюме или описание вакансии, чтобы получить вопросы под реальный стек позиции.
Будут ли вопросы про Express или NestJS?
Вопросы про фреймворки появляются там, где они уместны, но фокус на самом Node.js: event loop, стримы, обработка async-ошибок, производительность и безопасность. Если в загруженной вакансии указан конкретный фреймворк, вопросы подстроятся под него.
Сколько стоит мок-собеседование по Node.js?
Первое собеседование до 5 вопросов бесплатно. Дальше оплата за каждое собеседование, от $1.75, без подписки. В одном собеседовании может быть до 50 вопросов.