请求 - 响应周期是怎样的
Explain the request & response cycle
一句话:客户端发请求 → 经过一串中间件 → 匹配到路由 → 处理逻辑(查库等)→发出一个响应→ 结束。
Express 里具体经过什么:
- 解析——
express.json()把请求体解析成req.body(不加这个中间件req.body就是undefined, 这是最常见的新手问题) - 通用中间件—— CORS、日志、关联 id、限流
- 认证 / 鉴权—— 验 token,把用户挂到
req.user - 路由匹配—— 按注册顺序找第一个匹配的 method + path
- 校验 → 业务逻辑 → 查库
- 响应——
res.status(200).json(...) - 兜底—— 404 处理 + 错误处理中间件
三个必须知道的规则:
- 中间件按注册顺序执行, 必须调
next()才会往下走 —— 忘了调请求就永远挂着, 客户端一直转圈。 - 一个请求只能响应一次。重复
res.send会报Cannot set headers after they are sent。所以调用响应之后一定要return。 - 错误处理中间件有四个参数
(err, req, res, next)——少一个参数 Express 就认不出它是错误处理器, 这个坑很经典。
会追问:「异步函数里抛的错误 Express 会自动捕获吗?」——Express 4 里不会, 会变成未处理的 rejection,请求挂死。 要么自己 try/catch后 next(err), 要么包一层 asyncHandler。Express 5 才支持自动转发。
In one line: the client sends a request, it walks through a chain of middleware, a route matches, the handler does its work (hits the database and so on), one response goes out, done.
What it actually passes through in Express:
- Parsing —
express.json()turns the body intoreq.body(without that middlewarereq.bodyisundefined, which is the single most common beginner bug) - Generic middleware — CORS, logging, a correlation id, rate limiting
- Authentication and authorisation — verify the token, hang the user off
req.user - Route matching — the first registered method + path that matches wins
- Validation, then business logic, then the database
- Response —
res.status(200).json(...) - Catch-alls — the 404 handler and the error-handling middleware
Three rules you have to know:
- Middleware runs in registration order and you must call
next()for the chain to continue. Forget it and the request hangs forever while the client spins. - One request gets exactly one response. A second
res.sendthrowsCannot set headers after they are sent. So alwaysreturnafter you respond. - Error middleware takes four arguments,
(err, req, res, next)— drop one and Express no longer recognises it as an error handler. A classic trap.
Follow-up: “Does Express catch errors thrown inside an async function?” — not in Express 4. It becomes an unhandled rejection and the request hangs. Either try/catch yourself and call next(err), or wrap the handler in an asyncHandler. Express 5 forwards them for you.