Вопрос проверяет понимание однопоточной модели Node.js и того, как асинхронные операции с файловой системой влияют на обработку параллельных запросов.
Node.js использует однопоточную модель для выполнения JavaScript, но под капотом работает библиотека libuv, которая предоставляет пул потоков (по умолчанию 4 потока) для выполнения тяжёлых операций ввода-вывода, включая работу с файловой системой. Когда вы вызываете асинхронный метод, например fs.readFile, задача отправляется в этот пул, а основной поток продолжает обрабатывать другие запросы. Когда операция завершается, колбэк или промис возвращается в event loop и выполняется.
Асинхронные методы не блокируют event loop, поэтому сервер может принимать и обрабатывать другие запросы, пока файл читается в фоне. Это ключевое преимущество Node.js для I/O-интенсивных задач.
const fs = require('fs').promises;
async function handleRequest(req, res) {
// event loop свободен, пока файл читается в thread pool
const data = await fs.readFile('./big-file.txt', 'utf8');
res.end(data);
}
Синхронные методы, такие как fs.readFileSync, выполняются прямо в основном потоке. Пока файл читается, event loop полностью заблокирован: сервер не может обработать ни один другой запрос, таймеры не срабатывают, промисы не резолвятся.
const fs = require('fs');
function handleRequest(req, res) {
// блокирует весь сервер на время чтения
const data = fs.readFileSync('./big-file.txt', 'utf8');
res.end(data);
}
Пул потоков libuv по умолчанию имеет размер 4. Если одновременно запустить больше 4 тяжёлых файловых операций, остальные будут ждать в очереди. Размер пула можно изменить переменной окружения UV_THREADPOOL_SIZE, но это не отменяет необходимости использовать асинхронные API.
Итог: при использовании асинхронных методов Node.js не блокируется при параллельных запросах к файловой системе, а синхронные методы блокируют event loop и должны применяться только при старте приложения или в CLI-скриптах.