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. -
import
is 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 (
setImmediate
callbacks) -
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_threads
module) -
Child Processes (
child_process
module)
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.exports
is the actual exported object. -
exports
is 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
allocUnsafe
is 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-alive
header.
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
heapdump
module 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.js
for performance analysis. - Use
v8-profiler
for CPU profiling.
Top comments (0)