Skip to content

Chapter 8 of 8

Error Handling, Process Management, and Events

Robust Node.js applications need a clear strategy for handling errors, which can occur at multiple levels. Synchronous errors and those thrown inside async functions can be caught with try/catch. Callback-based APIs follow the error-first callback pattern, where the first argument to the callback is an Error object (or null if successful) and should always be checked before using the result. Promises expose errors through .catch(), and event-based APIs like streams emit an 'error' event that must be handled to avoid crashes.

For errors that escape all other handling, Node.js provides last-resort hooks: process.on('uncaughtException') catches synchronous errors that bubble all the way up, and process.on('unhandledRejection') catches Promise rejections without a .catch() handler. The recommended practice for both is to log the error, clean up any critical resources, and exit the process; attempting to keep running after an uncaught exception can leave the application in an undefined state. Building a solid error-handling strategy means combining all these layers appropriately for each kind of failure.

Underpinning much of Node.js is the EventEmitter class, the heart of its event-driven architecture. You create an instance with new EventEmitter(), register listeners with on() (or fire-once with once()), trigger events with emit(), and remove listeners with removeListener(). Many core modules, including streams, the http server, and process itself, inherit from EventEmitter, so understanding its pattern unlocks a great deal of Node.js behavior.

The global object in Node.js, named global (analogous to window in browsers), exposes several utilities. CommonJS modules can use __dirname and __filename to access the current file's path. The process object gives access to environment variables (process.env), command-line arguments (process.argv), the current working directory (process.cwd()), the process ID (process.pid), and memory statistics (process.memoryUsage()). It also allows graceful termination with process.exit(code) and handling of OS signals through process.on('signal', handler). Together, these facilities provide the runtime introspection and control needed to build reliable, well-behaved server applications.

All chapters
  1. 1Foundations of Node.js and the Event Loop
  2. 2Module Systems
  3. 3Streams and Buffers
  4. 4Asynchronous Programming
  5. 5Building Web Applications with Express
  6. 6Core Built-in Modules
  7. 7Package Management and Project Configuration
  8. 8Error Handling, Process Management, and Events

Drill it

Reading is not remembering. These come from the Nodejs Runtime deck:

Q

What is Node.js?

Node.js is a JavaScript runtime built on Chrome's V8 engine. It allows running JavaScript outside the browser, using an event-driven, non-blocking I/O model tha...

Q

What is the Node.js event loop?

The event loop is the mechanism that allows Node.js to perform non-blocking I/O operations despite JavaScript being single-threaded. It continuously checks the...

Q

What are the phases of the Node.js event loop?

Timers – executes setTimeout and setInterval callbacksPending callbacks – I/O callbacks deferred to next iterationPoll – retrieves new I/O eventsCheck – execute...

Q

What is the difference between setImmediate() and setTimeout()?

setImmediate() executes in the check phase of the event loop, after the poll phase completes. setTimeout(fn, 0) executes in the timers phase on the next iterati...