Async, Errors and Environment
💻 Node.jsHandle async errors, centralise error responses and keep secrets in environment variables.
Real servers fail: a database goes down, a request times out, a value is missing. Good error handling keeps the process alive.
- Use async route handlers safely.
- Add a central error handler.
- Read environment variables.
Async Errors
An error thrown inside an async handler is not caught by Express automatically in older versions. Wrap the handler and pass the error to next().
function asyncHandler(handler) {
return (request, response, next) => {
Promise.resolve(handler(request, response, next)).catch(next);
};
}
app.get("/students", asyncHandler(async (request, response) => {
const students = await loadStudents();
response.json(students);
}));Central Error Handler
One error middleware at the end of the file returns a consistent response and logs the details on the server.
app.use((error, request, response, next) => {
console.error(error);
response.status(500).json({ error: "Something went wrong" });
});Environment Variables
Never hard-code secrets. Read them from the environment and fail loudly at startup if a required value is missing.
const port = process.env.PORT ?? 3000;
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) {
throw new Error("DATABASE_URL is not set");
}Practice
- Wrap an async route with asyncHandler.
- Add a 404 handler for unknown routes.
- Read PORT and DATABASE_URL from the environment.
Hands-on exercise
Write an async route GET /students that:
1. Calls a function that may throw.
2. Passes errors to next().
3. Returns JSON on success.
Recap
Async handlers need explicit error forwarding. One central handler keeps responses consistent, and secrets belong in the environment.
Example
function asyncHandler(handler) {
return (request, response, next) => {
Promise.resolve(handler(request, response, next)).catch(next);
};
}
app.get("/students", asyncHandler(async (request, response) => {
const students = await loadStudents();
response.json(students);
}));
Exercises
1. Calls a function that may throw.
2. Passes errors to next().
3. Returns JSON on success.
Expected Output
Successful requests return data; failures reach the central error handler.