MEAN Node.js Async Patterns and Performance 5 — Questions and Answers
Question 1: What is the primary advantage of using Node.js Streams over reading an entire file into memory?
- Streams are always faster than buffer-based reads
- Streams process data in chunks, reducing memory footprint for large files (Correct answer)
- Streams automatically compress data during transfer
- Streams bypass the event loop for I/O operations
Correct answer: Streams process data in chunks, reducing memory footprint for large files
Streams process data piece-by-piece, so even multi-gigabyte files can be handled with minimal memory usage.
Question 2: What is the purpose of `process.nextTick()` versus `setImmediate()` in Node.js?
- `process.nextTick()` fires after I/O callbacks; `setImmediate()` fires before the current operation completes
- `process.nextTick()` fires before I/O callbacks in the current iteration; `setImmediate()` fires in the check phase of the next iteration (Correct answer)
- Both execute at identical priority in the event loop
- `process.nextTick()` is for synchronous code; `setImmediate()` is for async code
Correct answer: `process.nextTick()` fires before I/O callbacks in the current iteration; `setImmediate()` fires in the check phase of the next iteration
`process.nextTick()` callbacks run at the end of the current phase before moving to the next event loop phase, while `setImmediate()` runs in the check phase of the following iteration.
Question 3: In Node.js, what does the `--max-old-space-size` flag control?
- The maximum size of the worker thread pool
- The maximum heap memory allocated to the V8 engine (Correct answer)
- The maximum size of a single Buffer allocation
- The file descriptor limit for the process
Correct answer: The maximum heap memory allocated to the V8 engine
`--max-old-space-size=<MB>` sets the maximum heap size for V8's old generation space, preventing out-of-memory crashes for memory-intensive apps.
Question 4: What is a key characteristic of async generators in Node.js?
- They must resolve all values before yielding any
- They yield values lazily over time and can be iterated with `for await...of` (Correct answer)
- They are equivalent to regular generators but run in a worker thread
- They automatically batch multiple async operations for efficiency
Correct answer: They yield values lazily over time and can be iterated with `for await...of`
Async generators use `async function*` syntax and `yield` to produce values lazily, which can be consumed with `for await...of` loops.
Question 5: What problem does the `cluster` module solve in Node.js?
- It enables sharing a single database connection across requests
- It allows a Node.js app to spawn child processes that share the same server port, utilizing multiple CPU cores (Correct answer)
- It clusters similar HTTP requests together for batch processing
- It manages memory clustering across multiple V8 heap spaces
Correct answer: It allows a Node.js app to spawn child processes that share the same server port, utilizing multiple CPU cores
The `cluster` module forks the process into multiple workers that share the same listening port, enabling multi-core CPU utilization for Node.js servers.
Question 6: Which of the following correctly describes backpressure in Node.js streams?
- A security mechanism that limits inbound HTTP request rates
- A flow control signal from a writable stream indicating it cannot accept more data yet (Correct answer)
- The memory pressure caused by too many open file descriptors
- An error thrown when a stream's buffer overflows
Correct answer: A flow control signal from a writable stream indicating it cannot accept more data yet
Backpressure occurs when a writable stream's internal buffer is full; `write()` returns `false` and the readable source should pause until the `drain` event fires.
Question 7: What is the role of `worker_threads` in Node.js compared to `child_process`?
- `worker_threads` shares memory with the main thread via `SharedArrayBuffer`; `child_process` spawns isolated processes with separate memory (Correct answer)
- `worker_threads` is only for I/O tasks; `child_process` is for CPU-bound tasks
- Both share memory, but `worker_threads` is limited to 4 threads
- `child_process` is deprecated in favor of `worker_threads`
Correct answer: `worker_threads` shares memory with the main thread via `SharedArrayBuffer`; `child_process` spawns isolated processes with separate memory
Worker threads run in the same process and can share memory via `SharedArrayBuffer`, while child processes have fully isolated memory spaces and communicate via IPC.
What is the primary advantage of using Node.js Streams over reading an entire file into memory?