As perguntas da entrevista do Node.js testam sua compreensão do loop de eventos, padrões assíncronos, fluxos, desempenho e implantação de produção. Este guia cobre as perguntas mais comuns sobre Node.js para entrevistas com desenvolvedores back-end em 2026.
Perguntas principais do Node.js.
1. Explique o loop de eventos do Node.js
Node.js Event Loop Phases (in order):
1. timers — setTimeout, setInterval callbacks
2. pending I/O — I/O errors from previous iteration
3. idle/prepare — internal use
4. poll — retrieve new I/O events (MAIN PHASE)
5. check — setImmediate callbacks
6. close — close event callbacks (socket.destroy, etc.)
Microtask queue (runs BETWEEN each phase):
- process.nextTick() — higher priority than Promises
- Promise callbacks (.then/.catch)
Order of execution:
1. Synchronous code
2. process.nextTick() queue
3. Promise callbacks
4. setImmediate (check phase)
5. setTimeout (timers phase, even setTimeout(fn, 0))
// Demonstrate event loop order
console.log('1 - sync');
setTimeout(() => console.log('2 - setTimeout'), 0);
setImmediate(() => console.log('3 - setImmediate'));
Promise.resolve().then(() => console.log('4 - Promise'));
process.nextTick(() => console.log('5 - nextTick'));
console.log('6 - sync');
// Output: 1, 6, 5, 4, 3, 2
// sync → nextTick → Promise → setImmediate → setTimeout
2. O que é libuv e o que ele faz?
libuv é a biblioteca C que alimenta o loop de eventos e as operações de E/S do Node.js:
- Conjunto de threads: Lida com operações de bloqueio (E/S de arquivo, criptografia, DNS) em threads em segundo plano
- Ciclo de eventos: gerencia retornos de chamada assíncronos
- Abstração de plataforma: Funciona em Linux (epoll), macOS (kqueue), Windows (IOCP)
Tamanho padrão do pool de threads: 4 trabalhadores. Pode aumentar comUV_THREADPOOL_SIZE=8.
3. O que são streams Node.js e quando você os usa?
const fs = require('fs');
const zlib = require('zlib');
const { pipeline } = require('stream/promises');
// Streams: process data piece by piece, not all at once
// Memory efficient for large files
// Four types:
// Readable: fs.createReadStream, http.IncomingMessage
// Writable: fs.createWriteStream, http.ServerResponse
// Duplex: net.Socket (both read and write)
// Transform: zlib.gzip (modifies data as it passes through)
// Good: streams don't load entire file into memory
async function compressFile(input, output) {
await pipeline(
fs.createReadStream(input),
zlib.createGzip(),
fs.createWriteStream(output)
);
}
// BAD: loads entire file into memory
// const data = fs.readFileSync('huge-file.csv'); // could be 10GB!
// Streams for HTTP
const http = require('http');
http.createServer((req, res) => {
const stream = fs.createReadStream('large-file.mp4');
stream.pipe(res); // efficient streaming to browser
}).listen(3000);
4. Como você lida com erros no código Node.js assíncrono?
// 1. async/await with try/catch (most common in 2026)
async function getUser(id) {
try {
const user = await db.findUser(id);
if (!user) throw new Error('User not found');
return user;
} catch (error) {
logger.error({ error, id }, 'Failed to get user');
throw error; // re-throw or return error response
}
}
// 2. Express error handling middleware
app.get('/users/:id', async (req, res, next) => {
try {
const user = await getUser(req.params.id);
res.json(user);
} catch (error) {
next(error); // pass to error handler
}
});
app.use((error, req, res, next) => {
logger.error(error);
res.status(error.status || 500).json({ error: error.message });
});
// 3. Uncaught exceptions (last resort)
process.on('uncaughtException', (error) => {
logger.error('Uncaught exception:', error);
process.exit(1); // restart via PM2/supervisor
});
process.on('unhandledRejection', (reason, promise) => {
logger.error('Unhandled rejection:', reason);
// In Node.js 16+, this terminates the process
});
5. Explique os threads de trabalho em Node.js
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
// Main thread
if (isMainThread) {
// CPU-intensive work → offload to worker thread
const worker = new Worker(__filename, {
workerData: { data: largeDataArray }
});
worker.on('message', (result) => {
console.log('Result:', result);
});
worker.on('error', (error) => {
console.error('Worker error:', error);
});
} else {
// Worker thread
const { data } = workerData;
const result = expensiveComputation(data); // doesn't block main thread!
parentPort.postMessage(result);
}
// Use worker threads for:
// - CPU-intensive computation (image processing, crypto, compression)
// - Parallel data processing
// NOT needed for I/O operations (event loop handles those efficiently)
6. Como você dimensiona um aplicativo Node.js?
// 1. Cluster module (use all CPU cores)
const cluster = require('cluster');
const os = require('os');
if (cluster.isPrimary) {
const numCPUs = os.cpus().length;
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker) => {
console.log(`Worker ${worker.id} died. Restarting...`);
cluster.fork(); // auto-restart
});
} else {
require('./server'); // each worker runs the server
}
// 2. PM2 (recommended for production)
// pm2 start app.js -i max # cluster mode, max workers
// pm2 start app.js -i 4 # 4 workers
// pm2 monit # monitoring
// 3. Horizontal scaling
// Run multiple Node.js instances
// Load balance with nginx or AWS ALB
Sucesso da entrevista do Node.js: entenda profundamente o loop de eventos (fases, microtarefas versus macrotarefas), saiba quando usar fluxos para eficiência de memória, explique threads de trabalho versus cluster para dimensionamento e demonstre tratamento de erros assíncronos. As perguntas avançadas abrangem perfil de desempenho (–prof, clinic.js), detecção de vazamentos de memória e padrões de produção.
🔗 Share this article
✍️ Leave a Comment