Step 6: Save to a file
Right now everything is lost when the server stops. The simplest fix is to save the state to a JSON file after each change and load it when the server starts. (Real applications use a database, which the next step designs.) This example saves a to-do, then simulates a restart by loading the file again.
ExampleNode.js
const http = require("http");
const fs = require("fs");
const os = require("os");
const path = require("path");
const FILE = path.join(os.tmpdir(), "todos-demo.json");
function load() {
try {
return JSON.parse(fs.readFileSync(FILE, "utf8"));
} catch {
return { nextId: 1, todos: [] };
}
}
function save(state) {
fs.writeFileSync(FILE, JSON.stringify(state, null, 2));
}
const state = load();
function send(res, status, data) {
res.writeHead(status, { "Content-Type": "application/json" });
res.end(JSON.stringify(data));
}
function readBody(req) {
return new Promise((resolve) => {
let raw = "";
req.on("data", (c) => (raw += c));
req.on("end", () => resolve(raw ? JSON.parse(raw) : {}));
});
}
async function handle(req, res) {
if (req.method === "GET" && req.url === "/todos") return send(res, 200, state.todos);
if (req.method === "POST" && req.url === "/todos") {
const body = await readBody(req);
const todo = { id: state.nextId++, title: body.title, done: false };
state.todos.push(todo);
save(state); // write to disk after every change
return send(res, 201, todo);
}
send(res, 404, { error: "Not found" });
}
const server = http.createServer(handle);
server.listen(0, async () => {
const base = `http://localhost:${server.address().port}`;
await fetch(base + "/todos", { method: "POST", body: JSON.stringify({ title: "Saved to disk" }) });
console.log("on disk:", JSON.parse(fs.readFileSync(FILE, "utf8")).todos.length, "todo");
server.close();
// pretend the server restarted: a fresh load() finds the saved data
const again = load();
console.log("after restart:", again.todos.map((t) => t.title));
fs.unlinkSync(FILE);
});Output
on disk: 1 todo after restart: [ 'Saved to disk' ]
Writing the whole file on every change is fine for a small app, but it does not scale and two writes at the same moment could clash. That is exactly the problem databases solve.
Quick check
Why is writing a whole JSON file after every change limited?
Finish the quick check (and any code exercise) to complete this lesson, or mark it done yourself.
Tip: use the left and right arrow keys to move between lessons.