Use async/await in your routes and handle asynchronous errors without bringing the server down.
Open this lesson in KodokonYour real routes don't return in-memory arrays: they read files, query a database, call other APIs. All of these operations are asynchronous. You've known async/await since the JavaScript track; let's see how to use them cleanly in a server. First good news: a route function can be async.
import express from "express";
import { readFile } from "node:fs/promises";
const app = express();
app.get("/report", async (req, res) => {
const raw = await readFile("report.json", "utf8");
res.json(JSON.parse(raw));
});
app.listen(3000);This code works... as long as report.json exists. If the read fails, the promise is rejected and, depending on the Express version, the request stays without a response or the error leaks into the logs. The professional rule: every async route handles its errors, with try/catch and next(error).
app.get("/report", async (req, res, next) => {
try {
const raw = await readFile("report.json", "utf8");
res.json(JSON.parse(raw));
} catch (error) {
next(error);
}
});next(error) passes the error to the centralized error handler. It's a middleware with four parameters, declared after all the routes. A single place to log and format errors: that's what sets a maintainable API apart from a weekend project.
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({
error: "Internal server error"
});
});One last reflex to build: parallelism. Two independent operations chained with two awaits run one after the other. Promise.all launches them together: the response time is that of the slowest, not the sum of the two.
async function fetchUsers() {
return [{ id: 1, name: "Ada" }];
}
async function fetchTasks() {
return [{ id: 1, title: "Review the code" }];
}
app.get("/dashboard", async (req, res, next) => {
try {
const [users, tasks] = await Promise.all([
fetchUsers(),
fetchTasks()
]);
res.json({ users, tasks });
} catch (error) {
next(error);
}
});async route, what do you do with an error caught by catch?console.log and carry onnext(error) to pass it to the error handlerawaitsPromise.allsetTimeout between the twoerr firsterrorHandler