Answers to Top 50 Tricky Node.js Questions for Beginners
Core Concepts
1. What is the difference between require() and import?
-
require()is CommonJS (Node.js default), synchronous, and dynamically loads modules. -
importis ES6 (ECMAScript Modules), asynchronous, statically analyzed, and must be at the top level.
2. Explain the Node.js event loop architecture.
The event loop handles async operations in phases:
-
Timers (
setTimeout,setInterval) - Pending callbacks (executes I/O callbacks)
- Poll (retrieve new I/O events)
-
Check (
setImmediatecallbacks) -
Close callbacks (cleanup, e.g.,
socket.on('close'))
3. What is the purpose of __dirname and __filename?
-
__dirname: Absolute path of the current module's directory. -
__filename: Absolute path of the current module file.
4. How does Node.js handle child threads?
Node.js is single-threaded but uses libuv for async I/O operations. For CPU-heavy tasks, it can use:
-
Worker Threads (
worker_threadsmodule) -
Child Processes (
child_processmodule)
5. What is the difference between process.nextTick() and setImmediate()?
-
process.nextTick()executes before the next event loop tick (microtask). -
setImmediate()executes in the next iteration of the event loop (macrotask).
Modules System
6. How does Node.js resolve module paths in require()?
- Core modules (e.g.,
fs,http) -
node_modules(local and global) - Relative (
./file.js) or absolute paths (/path/to/file.js)
7. module.exports vs exports?
-
module.exportsis the actual exported object. -
exportsis just a reference tomodule.exports. - If you assign to
exports, it breaks the reference.
8. What problems can circular dependencies cause?
If A requires B and B requires A, Node.js may return an incomplete version of one module.
9. Core modules vs local modules?
-
Core modules (
fs,http) are built into Node.js. -
Local modules are user-created files (e.g.,
./myModule.js).
10. How to implement a custom require function?
function myRequire(moduleName) {
const code = fs.readFileSync(moduleName, 'utf8');
const wrapper = `(function(exports, require, module, __filename, __dirname) {${code}})`;
const module = { exports: {} };
eval(wrapper).call(module.exports, module.exports, myRequire, module, __filename, __dirname);
return module.exports;
}
Asynchronous Programming
11. Callbacks vs Promises vs Async/Await?
-
Callbacks: Nested functions (
fs.readFile(file, callback)) -
Promises:
.then()/.catch()chains -
Async/Await: Syntactic sugar over Promises (
async function() { await promise })
12. How to handle unhandled promise rejections?
process.on('unhandledRejection', (err) => {
console.error('Unhandled rejection:', err);
});
13. What is callback hell and how to avoid it?
Callback hell is nested callbacks. Solutions:
- Promises
- Async/Await
- Modularization
14. setTimeout(fn, 0) vs process.nextTick(fn)?
-
setTimeout(fn, 0)schedules in the next event loop tick. -
process.nextTick(fn)executes immediately after current operation.
15. How does Node.js handle concurrency?
- Single-threaded for JS execution.
- Uses libuv for async I/O (non-blocking operations).
Error Handling
16. What is the error-first callback pattern?
fs.readFile('file.txt', (err, data) => {
if (err) throw err;
console.log(data);
});
17. How to handle uncaught exceptions?
process.on('uncaughtException', (err) => {
console.error('Crash avoided:', err);
process.exit(1); // Recommended to restart
});
18. throw new Error() vs EventEmitter.emit('error')?
-
throw new Error()crashes the process if uncaught. -
EventEmitter.emit('error')allows handling via.on('error').
19. Why are domains deprecated?
Domains were used for error handling but were unreliable and complex. Use async context tracking instead.
20. Best practices for async/await error handling?
async function fetchData() {
try {
const data = await someAsyncTask();
} catch (err) {
console.error(err);
}
}
File System & Streams
21. fs.readFile() vs fs.createReadStream()?
-
readFile()loads entire file into memory. -
createReadStream()reads in chunks (better for large files).
22. How to implement a file watcher?
fs.watch('file.txt', (eventType, filename) => {
console.log(`${filename} changed!`);
});
23. Types of streams?
-
Readable (
fs.createReadStream) -
Writable (
fs.createWriteStream) -
Duplex (Read + Write, e.g.,
net.Socket) -
Transform (Modify data, e.g.,
zlib.createGzip)
24. How to pipe streams with error handling?
readable
.on('error', handleError)
.pipe(transform)
.on('error', handleError)
.pipe(writable)
.on('error', handleError);
25. What is backpressure in streams?
When data comes faster than it can be processed, streams buffer data. Solution:
- Use
.pause()/.resume() - Use
pipeline()for automatic handling
Events
26. How does EventEmitter work?
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const emitter = new MyEmitter();
emitter.on('event', () => console.log('Event fired!'));
emitter.emit('event');
27. .on() vs .once()?
-
.on()keeps listening. -
.once()triggers only once.
28. How to implement a custom EventEmitter?
class MyEmitter {
constructor() { this.events = {}; }
on(event, listener) {
if (!this.events[event]) this.events[event] = [];
this.events[event].push(listener);
}
emit(event, ...args) {
if (this.events[event]) this.events[event].forEach(listener => listener(...args));
}
}
29. Maximum listeners and how to change it?
Default: 10 listeners per event.
Change with:
emitter.setMaxListeners(20);
30. How to handle EventEmitter errors?
emitter.on('error', (err) => console.error('Emitter error:', err));
Answers to Top 50 Tricky Node.js Questions (Continued)
Buffers and Binary Data
31. What is a Buffer in Node.js?
A Buffer is a temporary storage for binary data (e.g., file streams, network packets).
const buf = Buffer.from('Hello', 'utf8');
console.log(buf); // <Buffer 48 65 6c 6c 6f>
32. Buffer.alloc() vs Buffer.allocUnsafe()?
-
Buffer.alloc(size): Creates a zero-filled Buffer (slower, secure). -
Buffer.allocUnsafe(size): Faster but may contain old data (must be filled manually).
33. Convert Buffer to JSON and vice versa?
const buf = Buffer.from('Hello');
const json = JSON.stringify(buf); // {"type":"Buffer","data":[72,101,108,108,111]}
const bufBack = Buffer.from(JSON.parse(json).data);
34. Security concerns with Buffers?
- Memory leaks (large Buffers not cleared).
-
Sensitive data exposure (Buffers may contain old data if
allocUnsafeis used). - Buffer overflow attacks (if not properly managed).
35. Concatenate multiple Buffers?
const buf1 = Buffer.from('Hello');
const buf2 = Buffer.from(' World');
const combined = Buffer.concat([buf1, buf2]); // <Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64>
HTTP & Web Servers
36. Create an HTTP server without Express?
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World');
});
server.listen(3000);
37. http.createServer() vs express()?
-
http.createServer()is low-level (manual routing, no middleware). -
express()is a framework (simplifies routing, middleware, error handling).
38. How does Node.js handle HTTP keep-alive?
- Reuses TCP connections for multiple requests (default in HTTP/1.1).
- Controlled by
Connection: keep-aliveheader.
39. req.on('data') vs req.on('end')?
-
req.on('data'): Fires when chunks of data arrive. -
req.on('end'): Fires when all data is received.
40. Handle file uploads without middleware?
const fs = require('fs');
const server = http.createServer((req, res) => {
if (req.url === '/upload' && req.method === 'POST') {
const file = fs.createWriteStream('upload.txt');
req.pipe(file);
req.on('end', () => res.end('Uploaded!'));
}
});
Process & Operating System
41. What is the process object?
Global object providing:
-
process.argv(CLI args) -
process.env(environment variables) -
process.exit()(terminate process)
42. Spawn a child process and communicate?
const { spawn } = require('child_process');
const child = spawn('ls', ['-lh']);
child.stdout.on('data', (data) => console.log(data.toString()));
43. spawn() vs exec() vs fork()?
-
spawn(): Streams output (best for large data). -
exec(): Buffers output (easier for small commands). -
fork(): Specialspawn()for Node.js scripts (IPC enabled).
44. Get OS information?
const os = require('os');
console.log(os.platform()); // 'linux', 'win32', etc.
console.log(os.cpus()); // CPU info
45. Access command-line arguments?
const args = process.argv.slice(2); // node script.js arg1 arg2 → ['arg1', 'arg2']
Testing & Debugging
46. Debug memory leaks?
- Use
node --inspect+ Chrome DevTools. - Check heap usage with
process.memoryUsage(). - Use
heapdumpmodule to analyze snapshots.
47. console.log() vs debugger?
-
console.log(): Manual logging. -
debugger: Pauses execution (works with--inspect).
48. Mock the filesystem for testing?
Use mock-fs or memfs:
const mock = require('mock-fs');
mock({ 'file.txt': 'Mocked content' });
console.log(fs.readFileSync('file.txt', 'utf8')); // 'Mocked content'
mock.restore();
49. What is --inspect?
Enables Chrome DevTools debugging:
node --inspect script.js
50. Profile a Node.js app?
- Use
node --prof+node --prof-process. - Use
clinic.jsfor performance analysis. - Use
v8-profilerfor CPU profiling.
Top comments (0)