Типичный пример блокировки:
function calculateHash(input) {
// Синхронная CPU-интенсивная операция блокирует Event Loop
let hash = 0;
for (let i = 0; i < 1000000; i++) {
hash += i * input.charCodeAt(i % input.length);
}
return hash;
}
Решение: Выносить тяжелые вычисления в Worker Threads или разбивать на части.
function leakyFunction() {
const obj = { largeData: new Array(1000000).fill('*') };
setInterval(() => {
console.log(obj.largeData.length); // obj никогда не будет удален GC
}, 1000);
}
fs.readFile('file1', (err1, data1) => {
fs.readFile('file2', (err2, data2) => {
fs.writeFile('result', data1 + data2, (err3) => {
// ...
});
});
});
Решение: Использовать async/await или promises.
// a.js
const b = require('./b');
module.exports = { b };
// b.js
const a = require('./a');
module.exports = { a };
const stream = fs.createReadStream('huge-file.txt');
stream.on('data', (chunk) => {
// Обработка без backpressure
});
Решение: Использовать .pipe() или обрабатывать паузы:
stream.on('data', (chunk) => {
if (!stream.write(processedChunk)) {
stream.pause();
// Возобновить когда drain
}
});
const { Worker } = require('worker_threads');
const sharedBuffer = new SharedArrayBuffer(1024);
new Worker(`
const { parentPort } = require('worker_threads');
const arr = new Uint8Array(sharedBuffer);
// Проблемы синхронизации доступа
`, { eval: true, workerData: { sharedBuffer } });
new Promise((_, reject) => reject(new Error('Необработанный rejection')));
Решение: Добавлять обработку process.on('unhandledRejection')
function starve() {
Promise.resolve().then(starve);
}
starve(); // Блокирует Event Loop
Для решения этих проблем важно:
Node.js мощная платформа, но требует глубокого понимания ее особенностей для эффективного использования.