Node and Express are the runtime and HTTP framework for your API. Topics here cover bootstrapping the app, parsing JSON bodies, and structured logging—everything that runs before a route handler executes. Master this layer first so later routers and controllers plug into a consistent foundation.
Async and await in Express
Matches Async and await in Express: Promises, async controllers, and awaiting Knex in services.
A Promise represents async work that will finish later (database, file, network). Knex queries return promises; Express handlers use async/await to read results cleanly.
Learn: Before async/await, Promises were the standard way to handle async results in Node. Knex still returns a Promise from every query builder chain. Understanding then/catch helps you read older examples; writing new code with async/await is usually clearer in controllers and services.
Mark controller functions async and await service/Knex calls. Always forward failures with next(err) so the error middleware can respond.
Learn: Async handlers must forward rejections with `next(err)`—otherwise Express may not invoke your error middleware. Wrapping async functions or using a small `asyncHandler` utility removes repetitive try/catch blocks.
Service functions return promises (or async functions that return data). Controllers await them; do not mix callback-style Knex with async/await in the same path.
Learn: Keep Promise-returning database code in services. The controller awaits one or more service calls and maps results to HTTP. If you return knex(...) directly from a service without await inside, the controller still awaits the same Promise—both styles work if errors propagate to next(err).
Supplementary examples
async service function
async function remove(pasteId) {
const deleted = await knex("pastes").where({ paste_id: pasteId }).del();
if (!deleted) {
const err = new Error("Paste not found");
err.status = 404;
throw err;
}
}
Course example
// service — return the Knex promise (or use async/await inside)
function listByUser(userId) {
return knex("pastes")
.where({ user_id: userId })
.orderBy("created_at", "desc");
}
// controller
async function list(req, res, next) {
try {
const rows = await service.listByUser(req.params.userId);
res.json({ data: rows });
} catch (err) {
next(err);
}
}