Вопрос проверяет понимание асинхронной модели Node.js и умение писать неблокирующий код для поддержания производительности приложения.
Event Loop в Node.js — это механизм, который обрабатывает асинхронные операции, позволяя приложению оставаться отзывчивым. Он блокируется, когда в основном потоке выполняется длительная синхронная задача (например, сложные вычисления, синхронный файловый ввод-вывод или бесконечный цикл), потому что цикл событий не может перейти к следующей фазе, пока текущий синхронный код не завершится.
fs.readFile вместо fs.readFileSync.worker_threads или разбивайте на части, используя setImmediate() или process.nextTick(), чтобы освобождать цикл событий между итерациями.Вместо выполнения долгого цикла за один раз, можно разбить его на части:
function processChunk(data, start, end, callback) {
// Тяжёлые вычисления над частью данных
let result = 0;
for (let i = start; i < end; i++) {
result += data[i] * Math.sqrt(i);
}
callback(result);
}
function processHeavyTask(data, chunkSize) {
let index = 0;
let finalResult = 0;
function nextChunk() {
if (index >= data.length) {
console.log('Итог:', finalResult);
return;
}
const end = Math.min(index + chunkSize, data.length);
processChunk(data, index, end, (chunkResult) => {
finalResult += chunkResult;
index = end;
// Освобождаем event loop перед следующей порцией
setImmediate(nextChunk);
});
}
nextChunk();
}
// Использование
const bigArray = new Array(1000000).fill(1);
processHeavyTask(bigArray, 10000);
Для действительно тяжёлых вычислений, которые нельзя эффективно разбить, создавайте отдельные потоки:
const { Worker } = require('worker_threads');
function runInWorker(scriptPath, data) {
return new Promise((resolve, reject) => {
const worker = new Worker(scriptPath, { workerData: data });
worker.on('message', resolve);
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));
});
});
}
// worker.js будет выполнять вычисления в фоне
Вывод: Избегайте блокировки event loop, используя асинхронные операции для I/O и вынося CPU-задачи в отдельные потоки или разбивая их на части. Это критически важно для поддержания высокой пропускной способности и отзывчивости Node.js-приложений, особенно серверов, обрабатывающих множество одновременных подключений.