Reading and writing files is one of the most common things a Node program does — loading configuration, persisting data, processing logs, generating reports. Node's `fs` module provides the file system operations, and the `path` module provides the tools to build and manipulate file paths correctly. The two are almost always used together. The `fs` module offers three flavours of nearly every operation: a promise-based API under `fs/promises`, a traditional callback API, and synchronous variants ending in `Sync`. For modern code the promise-based API is the default, because it composes with async/await and, as the event loop lesson established, keeps the single thread free while the disk works. The `path` module exists because file paths are deceptively tricky. Different operating systems use different separators — forward slashes on Unix and macOS, backslashes on Windows — and concatenating path strings by hand produces code that breaks when moved between systems. `path` handles these differences correctly so you never hardcode a separator. There is also a subtle but important wrinkle in ES Modules: the `__dirname` and `__filename` variables that CommonJS provided automatically do not exist in ESM, and must be reconstructed from `import.meta.url`. Knowing this saves a confusing early error. Mastering file and path handling — reading and writing safely, building cross-platform paths, handling the inevitable errors like a missing file, and streaming large files rather than loading them whole — is foundational for almost any real Node application, from build tooling to web servers.
25 minbeginner
File system and path
Analogy🏏Cricket
🏏 Think of it like cricket: Imagine you are following an India vs Australia match but you cannot watch it live — you ask a friend at the Wankhede Stadium to text you the final scorecard. Asking is the asynchronous operation: you do not stand frozen by your phone until the match ends. You go about your day (other code keeps running) and deal with the score when the text arrives. The promise your friend makes — 'I will send you the scorecard when the innings ends' — is exactly a JavaScript Promise: a commitment to deliver a value later. Just as your friend's promise is initially pending (innings in progress), then settles into either fulfilled (they text you '187/4') or rejected (they text 'rain stopped play, no result'), a Promise transitions once from pending to fulfilled or rejected and never flips back. Just as you plan in advance what you will do when the score arrives ('if India scored 180+, I will celebrate; if the feed fails, I will check another source'), `.then()` and `.catch()` register what happens on success and failure. The insight this reveals is that asynchronous programming is not about doing things faster — it is about not standing idle while you wait, so the single JavaScript thread stays free to handle everything else going on.
Lesson 14 of 36
0% complete