DEV Community

Abhay Singh Kathayat
Abhay Singh Kathayat

Posted on

Top 50 Tricky Node.js Questions for Beginners

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:

  1. Timers (setTimeout, setInterval)
  2. Pending callbacks (executes I/O callbacks)
  3. Poll (retrieve new I/O events)
  4. Check (setImmediate callbacks)
  5. 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()?

  1. Core modules (e.g., fs, http)
  2. node_modules (local and global)
  3. 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 to module.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;
}
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

17. How to handle uncaught exceptions?

process.on('uncaughtException', (err) => {
  console.error('Crash avoided:', err);
  process.exit(1); // Recommended to restart
});
Enter fullscreen mode Exit fullscreen mode

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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!`);
});
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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));
  }
}
Enter fullscreen mode Exit fullscreen mode

29. Maximum listeners and how to change it?

Default: 10 listeners per event.

Change with:

emitter.setMaxListeners(20);
Enter fullscreen mode Exit fullscreen mode

30. How to handle EventEmitter errors?

emitter.on('error', (err) => console.error('Emitter error:', err));
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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!'));
  }
});
Enter fullscreen mode Exit fullscreen mode

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()));
Enter fullscreen mode Exit fullscreen mode

43. spawn() vs exec() vs fork()?

  • spawn(): Streams output (best for large data).
  • exec(): Buffers output (easier for small commands).
  • fork(): Special spawn() 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
Enter fullscreen mode Exit fullscreen mode

45. Access command-line arguments?

const args = process.argv.slice(2); // node script.js arg1 arg2 → ['arg1', 'arg2']
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

49. What is --inspect?

Enables Chrome DevTools debugging:

node --inspect script.js
Enter fullscreen mode Exit fullscreen mode

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)