1basic
What does the Node.js event loop allow you to do?
✓Perform non-blocking I/O operations on a single thread
Node.js uses a single-threaded event loop with non-blocking I/O. Slow operations (disk, network) are offloaded to the OS or libuv thread pool. Their callbacks are queued and executed when the call stack is free, enabling high concurrency without threads.
2basic
What is the difference between require() and ES module import in Node.js?
✓require() is CommonJS and loads synchronously; import is ESM and is statically analysed
require() is CommonJS - it loads and executes modules synchronously at runtime. ES module import is statically analysed at parse time, enables tree-shaking, and is asynchronous in nature. Both are supported in modern Node.js (.mjs or "type":"module" in package.json for ESM).
3medium
What does process.nextTick() do?
✓Schedules a callback before I/O events in the current iteration of the event loop
process.nextTick() queues the callback in the 'nextTick queue', which is processed after the current operation completes and before I/O events or timers. It runs even before Promise microtasks in some Node.js versions, making it higher priority than setImmediate.
4basic
What is a Stream in Node.js?
✓An abstract interface for working with streaming data - data processed in chunks rather than all at once
Streams allow you to process data piece by piece (in chunks) rather than loading it all into memory. Node.js has four types: Readable, Writable, Duplex, and Transform. They are used for file I/O, HTTP, compression, and more.
5medium
What does the cluster module do in Node.js?
✓Allows you to create child processes that share the same server port to utilise multiple CPU cores
The cluster module forks worker processes from a master process. Each worker shares the same TCP port, distributing incoming connections across multiple CPU cores. This lets a Node.js server take advantage of multi-core systems.
6basic
What is middleware in Express.js?
✓A function with access to req, res, and next that can execute code, modify the request/response, or end the cycle
Middleware functions in Express have the signature (req, res, next). They can read/modify the request and response objects, execute any code, end the request-response cycle, or call next() to pass control to the next middleware.
7basic
What is the purpose of the package-lock.json file?
✓Records the exact versions of every installed dependency to guarantee reproducible installs
package-lock.json records the exact resolved version, download URL, and integrity hash for every package in the dependency tree. This ensures that npm install produces the same node_modules on every machine and CI run.
8medium
What does Buffer represent in Node.js?
✓A fixed-length raw binary data buffer allocated outside the V8 heap
Buffer represents a fixed-length sequence of bytes allocated outside the V8 JavaScript heap. It is used to handle binary data (files, network packets, crypto) before JavaScript had TypedArray support. Buffers are instances of Uint8Array.
9basic
What happens when you call fs.readFile() in Node.js?
✓It initiates an asynchronous file read; the callback is called when the read is complete
fs.readFile() is asynchronous. It initiates the read operation and immediately returns, allowing other code to run. Once the OS delivers the data, the callback is invoked with (err, data). For synchronous reading, use fs.readFileSync().
10basic
What is the __dirname variable in a CommonJS module?
✓The absolute path of the directory containing the current file
__dirname is automatically set to the absolute path of the directory that contains the current module file. It differs from process.cwd(), which returns the directory from which the Node.js process was launched.
11advanced
In which order does the Node.js event loop process its phases?
✓timers, pending callbacks, idle/prepare, poll, check, close callbacks
The event loop phases execute in this order: timers (setTimeout/setInterval callbacks), pending callbacks (I/O errors), idle/prepare (internal use), poll (retrieve new I/O events), check (setImmediate callbacks), and close callbacks (e.g., socket.on('close')). This cycle repeats continuously.
12advanced
What is the correct execution order of the following scheduling functions?
setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));
Promise.resolve().then(() => console.log('promise'));
process.nextTick(() => console.log('nextTick'));
✓nextTick, promise, timeout, immediate
process.nextTick runs first (nextTick queue), then Promise microtasks (.then callbacks), then timers phase (setTimeout with 0ms), then check phase (setImmediate). The nextTick queue drains completely before microtasks, and both drain before the event loop advances phases.
13advanced
What is the difference between setImmediate() and setTimeout(() => {}, 0)?
✓setImmediate runs in the check phase after poll; setTimeout with 0ms runs in the timers phase, so order depends on context
Within the main module, their order is non-deterministic. Inside an I/O callback, setImmediate always fires before setTimeout(fn, 0) because the check phase comes before the timers phase wraps around. setImmediate is preferred for deferring within I/O callbacks.
14advanced
What is backpressure in Node.js streams?
✓The condition where a Writable stream cannot process data as fast as a Readable produces it, signaling the producer to pause
Backpressure occurs when a Writable stream's internal buffer fills up. The write() method returns false, signaling the Readable to pause via pause(). When the Writable drains, it emits 'drain', and the Readable resumes. pipe() handles this automatically.
15medium
What does pipe() do in Node.js streams?
✓Connects a Readable stream to a Writable stream, automatically managing backpressure and data flow
readable.pipe(writable) attaches the Writable as a destination. Data flows automatically from the Readable to the Writable, and pipe() handles backpressure by pausing the Readable when write() returns false and resuming on 'drain'. It returns the destination for chaining.
16medium
What is the difference between a Duplex stream and a Transform stream?
✓A Duplex stream has independent read and write sides; a Transform stream's output is computed from its input
A Duplex stream (e.g., a TCP socket) has independent read and write sides that are unrelated to each other. A Transform stream (e.g., zlib.createGzip()) is a special Duplex where data written in is transformed and then readable out - the output derives from the input.
17medium
What does Buffer.alloc(10) produce compared to Buffer.allocUnsafe(10)?
✓Buffer.alloc creates a zero-filled buffer; Buffer.allocUnsafe skips zero-fill and may contain old memory data
Buffer.alloc(n) allocates n bytes and zero-fills them for safety. Buffer.allocUnsafe(n) allocates the same n bytes but skips initialization, which is faster but may expose old memory contents. Use allocUnsafe only when you will immediately overwrite all bytes.
18basic
What does Buffer.from('hello', 'utf8') do?
✓Allocates a new Buffer containing the UTF-8 byte representation of the string 'hello'
Buffer.from(string, encoding) creates a new Buffer from the given string using the specified encoding (default is 'utf8'). 'hello' in UTF-8 is 5 bytes. The resulting Buffer can be converted back with buf.toString('utf8').
19medium
What is the difference between child_process.spawn() and child_process.exec()?
✓spawn() streams stdout/stderr and suits large output; exec() buffers all output and suits small commands
spawn() streams stdio in real time, making it ideal for long-running processes or large output. exec() buffers the entire output in memory and calls back when done, capping at maxBuffer (default 1 MB). exec() also invokes a shell, so shell features like pipes work.
20medium
When should you use child_process.fork() instead of spawn()?
✓When spawning another Node.js module that needs IPC communication with the parent process
fork() is a specialization of spawn() designed for spawning Node.js processes. It establishes an IPC channel between parent and child, enabling process.send() and process.on('message') for structured communication. It is the foundation of the cluster module.
21advanced
What is the default size of libuv's thread pool in Node.js?
✓The default thread pool size is 4 threads, configurable via UV_THREADPOOL_SIZE up to 1024
libuv maintains a thread pool (default 4 threads) for operations the OS cannot do asynchronously, such as file system calls and crypto. You can increase it by setting the UV_THREADPOOL_SIZE environment variable before starting Node.js (max 1024).
22medium
What is the output of this code?
const EventEmitter = require('events');
const ee = new EventEmitter();
ee.on('data', (x) => console.log('listener1', x));
ee.emit('data', 42);
ee.removeAllListeners('data');
ee.emit('data', 99);
✓listener1 42 (second emit fires no listener because removeAllListeners was called)
The first emit('data', 42) fires the listener, printing 'listener1 42'. Then removeAllListeners('data') removes all listeners for that event. The second emit('data', 99) finds no listeners and does nothing. No error is thrown for emitting with no listeners.
23basic
What does ee.once('event', handler) do differently from ee.on('event', handler)?
✓once() registers a handler that automatically removes itself after it is invoked the first time
ee.once() wraps the handler so that after the first invocation it calls removeListener on itself. This is useful for one-time setup events like a server's 'listening' event or a stream's 'end' event.
24medium
What warning does Node.js emit when too many listeners are added to an EventEmitter?
✓Node.js prints a MaxListenersExceededWarning when listeners exceed 10 (the default limit)
By default, EventEmitter warns when more than 10 listeners are added for a single event, as this often indicates a memory leak (e.g., listeners added in a loop without cleanup). You can adjust the limit with emitter.setMaxListeners(n) or EventEmitter.defaultMaxListeners.
25medium
What is the purpose of util.promisify() in Node.js?
✓It wraps a Node.js error-first callback function and returns a Promise-returning version of it
util.promisify(fn) takes a function that follows the Node.js error-first callback convention (err, value) and returns a new function that returns a Promise. This allows you to use async/await with older callback-based APIs like fs.readFile.
26basic
What is the error-first callback convention in Node.js?
✓The callback's first argument is an error object (or null on success), and subsequent arguments are results
Node.js established the convention that asynchronous callbacks receive the error as their first parameter. If no error occurred, the first argument is null or undefined. This consistent pattern enabled libraries like async.js and util.promisify to work generically.
27medium
What does the following async/await code print?
async function fetchData() {
throw new Error('failed');
}
async function main() {
try {
await fetchData();
} catch (e) {
console.log('caught:', e.message);
}
}
main();
✓caught: failed (the try/catch inside an async function catches rejected Promises from await)
Inside an async function, try/catch correctly catches errors thrown by awaited Promises. When fetchData() throws, the rejection propagates to main(), where await unwraps it and the catch block handles it, printing 'caught: failed'.
28basic
What is the global 'process.env' object used for in Node.js?
✓It provides access to the shell environment variables of the running process
process.env is a plain object populated from the shell's environment variables at process start. It is the standard way to read configuration (API keys, ports, NODE_ENV) without hardcoding values. Libraries like dotenv load .env files into process.env at startup.
29medium
What is the difference between path.join() and path.resolve() in Node.js?
✓path.join concatenates segments with the OS separator; path.resolve builds an absolute path from the cwd or first absolute segment
path.join('a', 'b') simply joins segments with the platform separator and normalizes. path.resolve('a', 'b') processes segments right to left and builds an absolute path, prepending process.cwd() if no absolute segment is found. A leading '/' in a segment resets path.resolve.
30medium
How do you get the equivalent of __dirname in an ES module in Node.js?
✓Use import.meta.url with url.fileURLToPath and path.dirname to derive the directory path
__dirname is not available in ES modules. The equivalent pattern is: import { fileURLToPath } from 'url'; import { dirname } from 'path'; const __dirname = dirname(fileURLToPath(import.meta.url));. import.meta.url contains the file:// URL of the current module.
31basic
What does the following code print?
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello');
});
server.listen(3000, () => console.log('listening'));
✓listening is printed, and the server responds to all HTTP requests with status 200 and body 'Hello'
http.createServer(requestListener) creates an HTTP server. The listener receives IncomingMessage (req) and ServerResponse (res). writeHead sets the status code and headers, and res.end() sends the body and finalizes the response. server.listen() starts accepting connections.
32medium
What is the difference between app.use() and app.get() in Express.js?
✓app.use() mounts middleware for all HTTP methods and matches path prefixes; app.get() only matches GET requests with an exact path
app.use(path, fn) matches any HTTP method and performs prefix matching (e.g., '/api' matches '/api/users'). app.get(path, fn) only matches GET requests with exact path matching (ignoring query strings). app.use() is commonly used for middleware like body parsers.
33medium
How does Express.js handle errors thrown in route handlers?
✓Synchronous errors are caught by Express's default handler; async errors must be passed to next(err) explicitly
Express 4 catches synchronous throws from route handlers and forwards them to error middleware. Async errors (rejected Promises, async function throws) must be caught and passed to next(err) manually - or use Express 5, which catches async errors automatically.
34medium
What signature does an error-handling middleware in Express.js have?
✓(err, req, res, next) - four parameters, where Express identifies it as error-handling middleware
Express identifies error-handling middleware by its arity (4 parameters). The signature must be exactly (err, req, res, next), even if next is not used. Express skips this middleware for normal requests and routes errors to it via next(err).
35basic
What is the difference between req.params, req.query, and req.body in Express?
✓req.params holds named URL path segments; req.query holds query string key-value pairs; req.body holds the parsed request body
req.params contains named route parameters (e.g., /users/:id). req.query contains parsed query string values after '?'. req.body contains the parsed request body, populated by body-parsing middleware like express.json() or express.urlencoded().
36medium
What does the following code demonstrate about module caching?
// moduleA.js
const counter = { value: 0 };
module.exports = counter;
// main.js
const a = require('./moduleA');
const b = require('./moduleA');
a.value = 42;
console.log(b.value);
✓42 is printed because require() returns the cached module instance for both a and b
Node.js caches modules after the first require(). Subsequent require() calls return the same exported object from the cache. Since a and b reference the same object, mutating a.value is visible through b. This is stored in require.cache.
37advanced
What happens when two CommonJS modules require() each other (circular dependency)?
✓Each module gets a partially-completed export object of the other, reflecting only what was exported before the circular require
When A requires B and B requires A, Node.js breaks the cycle by returning A's partially-constructed exports object to B. Any exports added by A after the circular require call will not be visible to B at load time, which can cause undefined values and subtle bugs.
38advanced
How do ES module live bindings differ from CommonJS exports in handling circular dependencies?
✓ES module imports are live read-only views into the exporting module's bindings, so they update as the exporter initializes
ESM imports are live bindings - they reference the actual exported variable, not a copy. In circular ESM graphs, an importing module may see undefined initially but the binding updates once the exporter finishes initializing. CJS copies the exported value at require time.
39advanced
What does the following worker_threads code accomplish?
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
if (isMainThread) {
new Worker(__filename, { workerData: { n: 10 } });
} else {
parentPort.postMessage(workerData.n * 2);
}
✓The worker receives n=10 via workerData, computes 20, and sends the result to the main thread via postMessage
The main thread spawns a worker using the same file. isMainThread is false in the worker, so it reads workerData.n (10), computes 20, and sends it to the main thread with parentPort.postMessage(20). The main thread would receive this via worker.on('message').
40advanced
What is SharedArrayBuffer used for in Node.js worker threads?
✓It provides a raw memory buffer that can be shared across worker threads without copying
SharedArrayBuffer allocates memory that is accessible from multiple worker threads simultaneously without the overhead of message-passing serialization. Since multiple threads write concurrently, you must use Atomics operations to prevent data races.
41medium
What is the purpose of the 'crypto' module's randomBytes() function?
✓It generates cryptographically strong random bytes using the OS entropy source
crypto.randomBytes(size) generates cryptographically secure random bytes using the operating system's entropy source (e.g., /dev/urandom on Linux). It is suitable for tokens, salts, and keys. Math.random() is predictable and unsuitable for security purposes.
42medium
What does crypto.createHash('sha256').update('hello').digest('hex') return?
✓The SHA-256 hash of the string 'hello' as a hexadecimal string (one-way, fixed-length output)
createHash creates a Hash object. update() feeds data into it, and digest('hex') finalizes and returns the hash as a hex string. SHA-256 always produces 64 hex characters. Hashing is one-way - you cannot reverse it to get 'hello' back.
43medium
What is an HMAC and how do you create one in Node.js?
✓HMAC is a keyed hash for message authentication; use crypto.createHmac(algorithm, key).update(data).digest()
HMAC (Hash-based Message Authentication Code) combines a secret key with a hash algorithm to produce a tag that proves both message integrity and authenticity. In Node.js: crypto.createHmac('sha256', secret).update(message).digest('hex').
44advanced
What does process.on('uncaughtException', handler) do?
✓It catches synchronous exceptions that were not caught anywhere in the call stack
process.on('uncaughtException') catches synchronous exceptions that bubble up with no try/catch to handle them. The official Node.js recommendation is to use it only for cleanup and logging, then exit (process.exit(1)). Resuming execution after an uncaughtException is dangerous.
45medium
What does process.on('unhandledRejection', handler) catch?
✓It catches Promise rejections that were not handled with .catch() or try/catch in an async function
unhandledRejection fires when a Promise is rejected and no rejection handler is attached in the same tick. In Node.js 15+, an unhandled rejection causes the process to crash by default. The handler receives the reason (error) and the rejected Promise.
46medium
What does the following code print?
setTimeout(() => console.log('A'), 0);
Promise.resolve().then(() => console.log('B'));
console.log('C');
✓C, B, A (synchronous first, then microtasks, then macrotasks)
'C' prints synchronously. Then the microtask queue (Promise.resolve().then) drains, printing 'B'. Finally, the timers phase runs the setTimeout callback, printing 'A'. Microtasks always run before macrotasks (setTimeout, setImmediate).
47medium
What does fs.createReadStream() return and when would you use it?
✓It returns a Readable stream that emits file data in chunks, ideal for large files to avoid memory exhaustion
fs.createReadStream(path) creates a Readable stream that reads the file in chunks (default 64 KB highWaterMark). It is ideal for large files such as logs or media because data is processed incrementally, keeping memory usage low compared to fs.readFile().
48medium
What is the fs.promises API and how does it differ from callback-based fs methods?
✓fs.promises provides Promise-based versions of fs methods, enabling async/await without util.promisify
fs.promises (or import { readFile } from 'fs/promises') provides natively Promise-returning versions of all major fs methods. This allows clean async/await code without manual promisification. It is the preferred modern approach over fs.readFile with callbacks.
49basic
What is the npm 'scripts' field in package.json used for?
✓It defines named shell commands runnable with 'npm run <name>' for build, test, start, and other tasks
The scripts field lets you define project-level shell commands. Run them with 'npm run <name>'. Special names like 'start', 'test', 'build' can be run without 'run'. npm also has lifecycle scripts (preinstall, postinstall) that run automatically during install.
50basic
What is the difference between 'dependencies' and 'devDependencies' in package.json?
✓dependencies are required at runtime; devDependencies are only needed during development and are excluded from production installs
dependencies are packages needed for the application to run in production (e.g., express, mongoose). devDependencies are only needed during development (e.g., jest, eslint, typescript). Running 'npm install --production' or 'npm ci --omit=dev' skips devDependencies.
51medium
What is the difference between tilde (~) and caret (^) version ranges in package.json?
✓Tilde (~) allows patch-level updates only; caret (^) allows minor and patch updates but not major
~1.2.3 allows updates from 1.2.3 to <1.3.0 (patch only). ^1.2.3 allows updates from 1.2.3 to <2.0.0 (minor and patch). Caret is npm's default when you 'npm install' a package. Both respect semver's promise that minor versions are backward compatible.
52basic
What is the key difference between package-lock.json and yarn.lock?
✓package-lock.json is generated by npm and uses JSON format; yarn.lock is generated by Yarn and uses a custom text format
package-lock.json is npm's lock file in JSON format, including integrity checksums and resolved URLs. yarn.lock uses Yarn's own human-readable (but non-JSON) format. Both serve the same purpose - pinning exact dependency versions - but are not interchangeable between package managers.
53advanced
What does this cluster code do when it runs?
const cluster = require('cluster');
const http = require('http');
if (cluster.isMaster) {
cluster.fork();
cluster.fork();
} else {
http.createServer((_, res) => res.end('ok')).listen(3000);
}
✓The master forks two workers; both workers share port 3000 and handle incoming HTTP requests
cluster.isMaster is true in the primary process, which forks two workers. Each worker is a separate Node.js process. The cluster module uses OS-level socket sharing so all workers can accept connections on port 3000, distributing load across CPU cores.
54medium
What is IPC in the context of Node.js child processes and the cluster module?
✓IPC (Inter-Process Communication) is a channel allowing parent and child processes to exchange messages via process.send() and 'message' events
When a child process is forked (via cluster.fork() or child_process.fork()), Node.js creates an IPC channel between parent and child. Messages are sent with process.send(obj) and received with process.on('message', handler), using structured clone serialization.
55basic
What is the Node.js REPL and how do you start it?
✓REPL (Read-Eval-Print Loop) is an interactive shell started by running 'node' with no arguments
Running 'node' with no arguments starts the REPL. It reads an expression, evaluates it in the Node.js runtime, prints the result, and loops. The REPL is useful for quick experimentation. Special commands like .help, .exit, and .load are available.
56advanced
What does V8 garbage collection do in Node.js, and what are the two main heap spaces?
✓V8 GC reclaims memory from unreachable objects; the two main spaces are new space (short-lived) and old space (long-lived)
V8 uses a generational garbage collector. New space (young generation) holds recently allocated objects using a fast Scavenge algorithm. Surviving objects are promoted to old space (old generation), collected less frequently using Mark-Sweep and Mark-Compact algorithms.
57medium
What does the following EventEmitter code demonstrate?
const { EventEmitter } = require('events');
class MyEmitter extends EventEmitter {}
const emitter = new MyEmitter();
emitter.on('error', (err) => console.log('handled:', err.message));
emitter.emit('error', new Error('oops'));
✓handled: oops is printed because the 'error' listener intercepts the error event
Emitting 'error' on an EventEmitter without a listener throws the error and crashes the process. Here, there is an 'error' listener, so it is called normally with the Error object, printing 'handled: oops'. Always add error listeners to EventEmitters.
58medium
What happens if you emit 'error' on an EventEmitter with no 'error' listener?
✓Node.js throws the error as an uncaught exception, which will crash the process
EventEmitter treats 'error' events specially. If an 'error' event is emitted with no listener, Node.js throws the error as an uncaught exception. This will crash the process unless process.on('uncaughtException') is set. Always add an 'error' listener to streams and emitters.
59basic
What is the purpose of setInterval() and how do you stop it?
✓setInterval repeatedly calls the callback at the specified interval in milliseconds; stop it with clearInterval using the returned ID
setInterval(fn, ms) schedules fn to run every ms milliseconds, indefinitely. It returns an interval ID. clearInterval(id) cancels the interval. Not clearing intervals causes memory leaks because the callback and its closure are kept alive.
60basic
What does the following code log and why?
let count = 0;
const id = setInterval(() => {
count++;
console.log(count);
if (count === 3) clearInterval(id);
}, 100);
✓1, 2, 3 (clearInterval stops the timer after the third invocation)
The interval fires at ~100ms, ~200ms, and ~300ms. On the third call count is 3, clearInterval(id) is called synchronously before the callback returns, cancelling all future invocations. Only 1, 2, 3 are logged.
61medium
What does child_process.execFile() do differently from exec()?
✓execFile spawns the executable directly without invoking a shell, making it safer and slightly faster
execFile runs a binary directly without spawning a shell. This avoids shell injection vulnerabilities and reduces overhead. exec passes the command through /bin/sh, which allows shell features like pipes and redirection but is potentially unsafe with user-provided input.
62advanced
What does the 'poll' phase of the Node.js event loop do?
✓The poll phase retrieves new I/O events from the OS and executes their callbacks, blocking if the queue is empty
The poll phase retrieves I/O events from the OS. If there are callbacks to execute, they run. If the queue empties, the loop either waits (blocks) for new I/O or moves on if timers are pending. This is where most of the 'blocking' in Node.js actually occurs.
63advanced
What does the 'check' phase of the event loop execute?
✓The check phase executes setImmediate() callbacks registered in the current iteration
The check phase runs setImmediate() callbacks. It executes immediately after the poll phase completes. This is why setImmediate() always fires before the next timer tick when called inside an I/O callback - the check phase comes before wrapping back to timers.
64advanced
What does 'close callbacks' phase of the event loop handle?
✓It executes 'close' event callbacks for abruptly closed sockets and handles (e.g., socket.destroy())
The close callbacks phase handles 'close' events emitted when a stream or socket is destroyed abruptly (not closed cleanly). For example, if a TCP socket is destroyed, its 'close' event callback runs in this phase. Clean closes emit their events earlier in the cycle.
65medium
What happens when you call require() with a directory path in Node.js?
✓Node.js looks for index.js in that directory, or the file specified in the directory's package.json 'main' field
When require('./mydir') is called and mydir is a folder, Node.js first checks for mydir/package.json and its 'main' field. If absent, it tries mydir/index.js, then mydir/index.node. This convention lets you package a module as a folder.
66basic
What is the purpose of the 'main' field in package.json?
✓It specifies the entry point file resolved when another package requires this package
The 'main' field tells Node.js which file to use as the entry point when this package is required by another module. If absent, Node.js defaults to index.js. For ESM, the 'exports' field takes precedence over 'main'.
67advanced
What does the following Transform stream code output for input 'hello'?
const { Transform } = require('stream');
const upper = new Transform({
transform(chunk, encoding, callback) {
callback(null, chunk.toString().toUpperCase());
}
});
upper.write('hello');
upper.on('data', (d) => console.log(d.toString()));
✓HELLO (the transform function converts the chunk to uppercase before pushing it)
The transform function receives each chunk, converts it to uppercase with toUpperCase(), and passes it to callback(null, result), which pushes the transformed data downstream. Attaching the 'data' listener switches the stream to flowing mode and it prints 'HELLO'.
68medium
What does require.resolve() do in Node.js?
✓It returns the resolved absolute file path of a module without loading or executing it
require.resolve(id) runs the module resolution algorithm and returns the resolved absolute path without loading the file. It is useful for checking whether a module exists or getting its path for use in other tools, without the side effect of executing the module.
69advanced
How do you delete a cached module from require.cache to force a fresh load?
✓Delete the entry with: delete require.cache[require.resolve('./myModule')]
require.cache is a plain object keyed by resolved file paths. To remove a module: delete require.cache[require.resolve('./myModule')]. The next require() call will re-execute the module file. This is sometimes used in hot-reloading scenarios or tests.
70basic
What does the dotenv package do and how is it typically used?
✓dotenv reads a .env file and loads its key-value pairs into process.env at startup
dotenv parses a .env file (KEY=value format) and merges those values into process.env. It is called with require('dotenv').config() or import 'dotenv/config' at application startup, before any other code reads process.env. The .env file should never be committed to version control.
71advanced
What does this async generator function do?
async function* paginate(url) {
while (url) {
const res = await fetch(url);
const data = await res.json();
yield data.items;
url = data.nextPage;
}
}
✓It yields each page's items one at a time, fetching the next page on demand via async iteration
An async generator (async function*) can use both await and yield. Each 'for await...of' iteration triggers the next fetch. This lazily paginates: one page is fetched per iteration, keeping memory use constant regardless of total pages.
72advanced
What is the purpose of the Node.js 'events' module's EventEmitter.captureRejections option?
✓When true, async listener errors are automatically routed to the emitter's 'error' event instead of crashing
With captureRejections: true (or EventEmitter.captureRejections = true), if an async event listener returns a rejected Promise, Node.js automatically routes the error to the emitter's 'error' event handler instead of letting it become an unhandledRejection.
73medium
What does the following http server code expose as a security concern?
const http = require('http');
http.createServer((req, res) => {
const name = req.url.slice(1);
res.end('Hello ' + name);
}).listen(3000);
✓The server reflects unsanitized user input into the response, enabling reflected XSS if rendered as HTML
If a browser renders the response as HTML, an attacker could craft a URL like /<script>alert(1)</script> to inject JavaScript (reflected XSS). Always sanitize or encode user-provided data before including it in responses, especially HTML responses.
74medium
What does process.exit(1) do versus letting the process end naturally?
✓process.exit(1) immediately terminates the process with exit code 1, skipping pending async operations and 'exit' event listeners
process.exit(code) immediately terminates the process. It does not wait for pending I/O, timers, or async operations. The exit code (0 = success, non-zero = failure) is read by the calling shell or CI system. Natural termination waits for the event loop to drain.
75basic
What is the output of this code?
function add(a, b) {
return new Promise((resolve) => {
setTimeout(() => resolve(a + b), 100);
});
}
async function main() {
const result = await add(2, 3);
console.log(result);
}
main();
✓5 is printed after approximately 100 milliseconds
add() returns a Promise that resolves to 5 after 100ms. await suspends main() until the Promise resolves, then assigns 5 to result. console.log prints 5. This demonstrates the core pattern of using async/await with Promise-based APIs.
76medium
What is the purpose of Promise.all() and what happens if one Promise rejects?
✓Promise.all() runs Promises concurrently and rejects immediately if any Promise rejects, discarding other results
Promise.all(iterable) waits for all Promises to fulfill. If any one rejects, the whole Promise.all() immediately rejects with that reason - the fast-fail behavior. Other Promises continue running but their results are ignored. Use Promise.allSettled() if you need all results.
77medium
What does Promise.allSettled() return that makes it different from Promise.all()?
✓Promise.allSettled() always resolves with an array of objects describing each Promise's outcome, whether fulfilled or rejected
Promise.allSettled() waits for all Promises to settle (fulfill or reject). It always resolves with an array of result objects: { status: 'fulfilled', value } or { status: 'rejected', reason }. It never rejects itself, making it ideal when you need all results regardless of failures.
78basic
What does the following code print?
const p = Promise.resolve(42);
p.then((v) => {
console.log('then1:', v);
return v * 2;
}).then((v) => {
console.log('then2:', v);
});
✓then1: 42, then2: 84 (the returned value from a .then() handler becomes the next .then()'s input)
Promise chaining works by passing the return value of each .then() handler as the argument to the next. The first handler receives 42 and returns 84 (42 * 2). The second handler receives 84. Both log their values in order.
79basic
What is the purpose of the Node.js 'os' module?
✓The os module provides operating system-related utility functions like cpu info, memory, hostname, and platform
The 'os' module exposes OS-level info: os.cpus() (CPU count and model), os.totalmem() / os.freemem() (RAM), os.hostname(), os.platform() ('linux', 'darwin', 'win32'), os.tmpdir(), and os.EOL (line ending). Useful for cross-platform scripts and diagnostics.
80medium
What does the following code demonstrate about readable streams?
const { Readable } = require('stream');
const readable = new Readable({ read() {} });
readable.push('chunk1');
readable.push('chunk2');
readable.push(null);
readable.on('data', (chunk) => console.log(chunk.toString()));
✓chunk1 and chunk2 are printed; pushing null signals the end of the stream
Pushing chunks to a Readable buffers them internally. Pushing null signals end-of-stream. Attaching a 'data' listener switches the stream to flowing mode, emitting each buffered chunk separately. 'chunk1' and 'chunk2' print on separate lines.
81advanced
What is the highWaterMark option in Node.js streams?
✓highWaterMark defines the internal buffer size threshold; when exceeded, the stream applies backpressure
highWaterMark (default 16 KB for byte streams, 16 objects for object mode) is the buffer size threshold. When the internal buffer exceeds highWaterMark, push() returns false (Readable) or write() returns false (Writable), signaling the producer to pause and allowing backpressure to take effect.
82advanced
What is a common use-case for Node.js worker threads versus the cluster module?
✓Worker threads suit CPU-intensive tasks within one process; cluster suits scaling HTTP servers across CPU cores
Worker threads are ideal for CPU-intensive work (image processing, parsing) because they share memory via SharedArrayBuffer and avoid IPC serialization overhead. Cluster is designed to scale network servers across cores - each worker is a full Node.js process that handles HTTP connections independently.
83advanced
What does the following code print and why?
process.nextTick(() => console.log('nextTick'));
setImmediate(() => console.log('immediate'));
Promise.resolve().then(() => console.log('promise'));
✓nextTick, promise, immediate (nextTick queue first, then microtasks, then check phase)
The nextTick queue drains first (process.nextTick has highest priority). Then the Promise microtask queue drains. Finally, the check phase runs setImmediate. This order is fundamental to Node.js async scheduling and applies regardless of call location.
84medium
What does the 'net' module provide in Node.js?
✓The 'net' module provides a low-level API for creating TCP and IPC stream servers and clients
The 'net' module enables raw TCP networking: net.createServer() creates a TCP server, and net.createConnection() creates a TCP client. The 'http' module is built on top of 'net'. It is used for building custom protocols, proxies, and non-HTTP TCP services.
85basic
What does the following code print?
async function run() {
const results = await Promise.all([
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3),
]);
console.log(results);
}
run();
✓[1, 2, 3] because Promise.all resolves to an array of the fulfilled values in order
Promise.all() resolves to an array of fulfilled values in the same order as the input, regardless of resolution order. await unwraps the single Promise returned by Promise.all, so results is [1, 2, 3].
86medium
What does the 'zlib' module provide in Node.js?
✓The zlib module provides gzip, deflate, and brotli compression and decompression, typically via Transform streams
The zlib module wraps the zlib C library, providing compression algorithms (gzip, deflate, brotli) as Transform streams. Common use: piping a file read stream through zlib.createGzip() to compress it before writing or sending it over HTTP.
87medium
What does the following code do?
const { pipeline } = require('stream');
const fs = require('fs');
const zlib = require('zlib');
pipeline(
fs.createReadStream('input.txt'),
zlib.createGzip(),
fs.createWriteStream('output.gz'),
(err) => { if (err) console.error(err); }
);
✓It reads input.txt, compresses it with gzip, writes the result to output.gz, and handles errors via callback
stream.pipeline() connects streams in order and handles backpressure, cleanup, and error propagation automatically. Here it reads input.txt, compresses via gzip Transform, and writes to output.gz. The callback is called on completion or error. It is preferred over manual pipe() chaining.
88basic
What does the 'url' module's URL class provide in Node.js?
✓The URL class parses URL strings into structured objects with properties like hostname, pathname, and searchParams
The WHATWG URL class (available globally in Node.js 10+) parses a URL string into components: protocol, hostname, port, pathname, search, hash, and a URLSearchParams object. new URL('https://example.com/path?q=1').searchParams.get('q') returns '1'.
89medium
What is the difference between 'fs.watch()' and 'fs.watchFile()' in Node.js?
✓fs.watch() uses native OS file system events; fs.watchFile() uses stat-based polling with a configurable interval
fs.watch() uses OS-native events (inotify on Linux, kqueue on macOS, FSEvents on macOS, ReadDirectoryChangesW on Windows) and is more efficient. fs.watchFile() polls the file's stat at a configurable interval (default 5007ms). fs.watch() is more responsive but has cross-platform quirks.
90advanced
What does the following Express router code do?
const router = require('express').Router();
router.param('userId', (req, res, next, id) => {
req.user = { id };
next();
});
router.get('/users/:userId', (req, res) => {
res.json(req.user);
});
✓router.param() registers a callback that runs before route handlers whenever :userId appears, useful for loading resources
router.param(name, callback) registers a pre-handler that fires whenever a route containing :name is matched. It is typically used to load a resource (e.g., find a user by ID) and attach it to req before the main route handler runs, reducing code duplication across routes.
91advanced
What does the following code reveal about the pending callbacks phase?
const net = require('net');
const server = net.createServer();
server.listen(9999);
server.on('error', (err) => {
console.log('phase: pending callbacks -', err.code);
});
✓I/O error callbacks like EADDRINUSE are deferred to the pending callbacks phase of the next event loop tick
The pending callbacks phase handles I/O callbacks deferred from the previous cycle, including some TCP error callbacks like ECONNREFUSED and EADDRINUSE. This is why certain I/O errors feel asynchronous even when they are predictable at server startup.
92medium
What is the purpose of the 'querystring' module (and its modern replacement) in Node.js?
✓querystring serializes and parses URL query strings; the modern replacement is URLSearchParams from the 'url' module
The 'querystring' module (legacy) parses and serializes URL query strings: querystring.parse('a=1&b=2') returns { a: '1', b: '2' }. The modern replacement is the WHATWG URLSearchParams class, available globally, which has a more complete API and is actively maintained.
93advanced
What does the following code do and what is its risk?
const { exec } = require('child_process');
app.get('/ping', (req, res) => {
const host = req.query.host;
exec('ping -c 1 ' + host, (err, stdout) => {
res.send(stdout);
});
});
✓The code is vulnerable to OS command injection because user input is concatenated directly into a shell command
Concatenating user input into exec() commands is a classic OS command injection vulnerability. An attacker could send host=; rm -rf / and the shell would execute both commands. Always use execFile() with arguments array, or validate and sanitize the input rigorously.
94basic
What does the 'assert' module provide in Node.js?
✓The assert module provides assertion functions that throw AssertionError when conditions are not met, useful for testing invariants
The built-in 'assert' module provides simple assertion functions like assert.strictEqual(), assert.deepStrictEqual(), assert.throws(), and assert.ok(). When an assertion fails, it throws an AssertionError. It is used for low-level invariant checks and simple unit tests.
95medium
What does the following ESM code demonstrate about named vs default exports?
// math.mjs
export const add = (a, b) => a + b;
export default function multiply(a, b) { return a * b; }
// main.mjs
import multiply, { add } from './math.mjs';
console.log(add(2, 3), multiply(2, 3));
✓5 6 is printed; multiply is the default export and add is a named export, both imported in one statement
ESM allows mixing named and default exports. The default export is imported without braces (multiply), and named exports are imported with braces ({ add }). Both are resolved statically. add(2,3) is 5 and multiply(2,3) is 6, so '5 6' is printed.
96advanced
What does the 'timers/promises' module provide in modern Node.js?
✓It provides Promise-based versions of setTimeout, setImmediate, and setInterval for use with async/await
The 'timers/promises' module (Node.js 15+) exports setTimeout, setImmediate, and setInterval as Promise-returning functions. This enables 'await setTimeout(1000)' for clean async delays without wrapping callbacks in Promises manually.
97basic
What does the 'readline' module provide in Node.js?
✓readline provides an interface for reading input line by line from a Readable stream, including stdin
The 'readline' module creates a line-by-line reader over a Readable stream. readline.createInterface({ input: process.stdin }) reads user input line by line. It is used for interactive CLI tools and for processing large text files efficiently without loading the whole file.
98advanced
What does the following code print and what concept does it demonstrate?
const obj = { name: 'Node' };
const worker = new (require('worker_threads').Worker)(
`const { workerData, parentPort } = require('worker_threads');
parentPort.postMessage(workerData.name.toUpperCase());`,
{ eval: true, workerData: obj }
);
worker.on('message', (msg) => console.log(msg));
✓NODE is printed; workerData is cloned to the worker using the structured clone algorithm
workerData is transferred to the worker via the structured clone algorithm - it is a deep copy, not a reference. The worker receives a clone of obj, reads name ('Node'), calls toUpperCase(), and posts 'NODE' back. eval: true allows passing a code string as the worker script.
99basic
What does the NODE_ENV environment variable conventionally control in Node.js applications?
✓NODE_ENV conventionally signals the deployment context ('development', 'test', 'production') and affects error handling, logging, and performance optimizations
NODE_ENV is a widely-adopted convention (not enforced by Node.js itself). Express enables production optimizations when NODE_ENV='production' (template caching, less verbose errors). Libraries check it to toggle debug logging. Setting it to 'test' allows test-specific behavior without code changes.
100advanced
What does the following code demonstrate about error propagation in Promise chains?
Promise.resolve()
.then(() => { throw new Error('step1 failed'); })
.then(() => console.log('step2'))
.catch((err) => console.log('caught:', err.message))
.then(() => console.log('step4'));
✓caught: step1 failed, step4 (the error skips step2, catch handles it, then the chain resumes)
When a .then() throws, the error skips all subsequent .then() handlers until a .catch() (or .then(null, handler)) is reached. After catch handles the error and returns normally, the chain resumes. step2 is skipped, catch prints 'caught: step1 failed', then step4 prints.