Node.js
fs persistence
Save and load data with fs.
Saving to a file with fs
Now we will save tasks to disk and load them back. Node.js's fs module does file operations. fs.writeFileSync(file, data) writes data to a file; fs.readFileSync(file, "utf8") reads the file as a string.
To save tasks we turn the array into a string with JSON.stringify(tasks, null, 2). The null, 2 gives indented formatting; the file stays readable. To load we turn the string back into an object with JSON.parse(raw). readFileSync throws if the file does not exist; so we wrap it in try/catch and set tasks = [] on error. This way the app does not crash on first run when no file exists.
Safe reading with try/catch
The loadTasks function uses try/catch. Inside the try block fs.readFileSync is called; if the file is missing it throws. The catch block catches the error and sets tasks = [].
This pattern is critical on first run when no file exists yet. If the error is not caught the app crashes. The catch (e) parameter receives the error object; we do not use it but the conventional name is e. This is the basic error handling pattern: anticipate an expected error and continue with a safe default.
Exercise Add the saveTasks and loadTasks functions
Take the previous lesson's solution (the fs module is already imported). Add saveTasks(): call fs.writeFileSync(DATA_FILE, JSON.stringify(tasks, null, 2)). Add loadTasks(): in try/catch read with fs.readFileSync(DATA_FILE, "utf8"), assign to tasks with JSON.parse(raw); on error set tasks = []. The last lines are ready: addTask("Email"); completeTask(1); saveTasks(); console.log("Saved");
Show example solution
const path = require("path");
const fs = require("fs");
const DATA_FILE = path.join("data", "tasks.json");
function createTask(id, title) {
return { id: id, title: title, done: false };
}
let tasks = [];
tasks.push(createTask(1, "Shopping"));
function addTask(title) {
const id = tasks.length + 1;
tasks.push(createTask(id, title));
}
function completeTask(id) {
const task = tasks.find(function(t) { return t.id === id; });
if (task) { task.done = true; }
}
function saveTasks() {
fs.writeFileSync(DATA_FILE, JSON.stringify(tasks, null, 2));
}
function loadTasks() {
try {
const raw = fs.readFileSync(DATA_FILE, "utf8");
tasks = JSON.parse(raw);
} catch (e) {
tasks = [];
}
}
addTask("Email");
completeTask(1);
saveTasks();
console.log("Saved");
Test yourself
-
Which method writes synchronously?
fs.writeFileSync(DATA_FILE, data)
- fs.readFile
- fs.open
- fs.appendFile
- fs.writeFileSync
Show answer
fs.writeFileSync — writeFileSync writes to a file synchronously.
-
Match each piece to its role
- fs.writeFileSync
- Writes the array to a file
- fs.readFileSync
- Reads the file as a string
- JSON.stringify
- Turns the array into a string
- JSON.parse
- Turns the string into an array
-
Complete the saveTasks body
function saveTasks() {
fs.____(DATA_FILE, JSON.stringify(tasks, null, 2));
}
Show answer
function saveTasks() {
fs.writeFileSync(DATA_FILE, JSON.stringify(tasks, null, 2));
}
Next lesson: Putting it together