一、前言
上篇文章我们介绍了express-generator的请求体解析,重点讲了常用的请求体数据格式(JSON/URL 编码的表单数据)以及一个FILE文件上传,同时搭配代码示范进行辅助理解。
二、本篇重点
我们继续第一阶段的知识,本篇把最后两个知识点(路由中间件和错误请求)讲完,顺利完成第一阶段的初步认识和学习。
三、知识点:路由中间件
1、路由中间件是什么?
路由中间件是 Express 中的一个强大功能,它允许你在处理请求之前和之后执行自定义逻辑。中间件可以用于各种任务,如日志记录、身份验证、数据验证等。
路由中间件可以被理解为一个函数,它接收三个参数:
req
(请求对象)、res
(响应对象)和next
(函数)。这个函数可以对这三个参数进行操作,并且通过这些操作来影响 Express 服务器的行为。以下是路由中间件的一些关键点:
接收参数:
req
(请求对象):包含了请求的所有信息,如请求方法、URL、请求头、请求体等。中间件可以读取和修改req
对象的属性。res
(响应对象):用于向客户端发送响应。中间件可以发送响应、设置响应头、设置响应状态码等。next
(函数):调用next()
可以将控制权传递给下一个中间件或路由处理函数。如果不调用next()
,请求处理流程将停止。操作和影响:
- 读取和修改请求信息:中间件可以读取请求中的数据,如解析请求体、获取请求头信息等。也可以修改请求对象,如添加自定义属性、修改请求参数等。
- 发送响应:中间件可以直接向客户端发送响应,结束请求处理流程。例如,可以发送错误响应、重定向响应等。
- 执行自定义逻辑:中间件可以执行各种自定义逻辑,如身份验证、日志记录、数据验证、缓存处理等。
- 错误处理:中间件可以捕获和处理错误,将错误传递给错误处理中间件,或者直接发送错误响应。
中间件的执行顺序
- 顺序执行:中间件按照它们在
app.use()
中被调用的顺序执行。每个中间件都有机会处理请求,并决定是否将控制权传递给下一个中间件。- 调用
next()
:中间件通过调用next()
函数来将控制权传递给下一个中间件。如果中间件不调用next()
,请求处理流程将停止,不会执行后续的中间件或路由处理函数。
2、express-generator创建express应用程序,默认使用的路由中间件
首先让我们看看使用express-generator创建一个express应用程序时,app.js默认使用的路由中间件有哪些
知识点相关介绍:
1.
logger('dev')
- 作用:使用
morgan
日志记录器中间件,记录 HTTP 请求的详细信息。- 配置:
'dev'
是morgan
的预定义格式之一,它会在开发环境中提供简洁的彩色日志输出,包括请求方法、URL、响应状态码和响应时间等。- 使用场景:用于开发环境中的日志记录,帮助开发者监控和调试应用程序。
2.
express.json()
- 作用:解析 JSON 格式的请求体。
- 使用场景:用于处理客户端发送的 JSON 数据,例如 API 请求中的 JSON 数据。
3.
express.urlencoded({ extended: false })
- 作用:解析 URL 编码的请求体。
- 配置:
{ extended: false }
表示使用内置的查询字符串解析器,它只能解析简单的键值对,不支持嵌套对象或数组。- 使用场景:用于处理 HTML 表单提交的数据,这些数据通常以
application/x-www-form-urlencoded
格式发送。4.
cookieParser()
- 作用:解析客户端发送的 Cookie。
- 使用场景:用于处理客户端发送的 Cookie,以便在服务器端进行身份验证或其他需要 Cookie 的操作。
5.
express.static(path.join(__dirname, 'public'))
- 作用:提供静态文件服务。
- 配置:
path.join(__dirname, 'public')
指定了静态文件的目录,通常是项目的public
目录。- 使用场景:用于提供网站的静态资源,如图片、CSS、JavaScript 文件等,使得客户端可以直接访问这些文件。
3、动手写一个简单的路由中间件
const express = require('express');
const app = express();
// 定义一个日志记录中间件
function logRequest(req, res, next) {
const { method, url } = req;
console.log(`Received ${method} request for ${url}`);
next(); // 调用下一个中间件
}
// 使用中间件
app.use(express.json()) //解析请求体数据
app.use(logRequest); //日志记录中间件
app.get('/', (req, res) => {
res.send('Hello, World!');
});
app.post('/user', (req, res) => {
console.log("接收的请求体参数>>>",req.body);
res.send(req.body);
});
app.listen(3009, () => {
console.log('Server is running on port 3009');
});
启动服务器,打开apipost工具进行路由测试
在这个示例中,
logRequest
中间件会在每个请求到达时记录请求方法和 URL。
四、知识点:错误处理
错误处理是任何 Web 应用程序的重要组成部分。在 Express 中,错误处理中间件用于捕获和处理在请求处理过程中发生的错误。
常用知识点
- 错误处理中间件:必须有四个参数:
err
、req
、res
和next
。- 抛出错误:在中间件或路由处理函数中使用
next(err)
来传递错误。- 自定义错误对象:可以创建自定义错误对象以提供更详细的错误信息。
1、常见的错误类型
- 语法错误:由于代码编写错误导致的错误,如拼写错误、语法不正确等。
- 运行时错误:在代码执行过程中发生的错误,如访问未定义的变量、调用不存在的方法等。
- HTTP 错误:与 HTTP 请求和响应相关的错误,如 404(未找到)、500(服务器内部错误)等。
- 输入验证错误:由于用户输入不符合预期格式或规则导致的错误。
- 数据库错误:与数据库操作相关的错误,如查询失败、连接错误等。
2、错误处理中间件
错误处理中间件是 Express 中用于处理错误的特殊中间件。它有四个参数:
err
、req
、res
和next
。当在中间件或路由处理函数中调用next(err)
时,控制权会传递给错误处理中间件。
一个简单的代码示范
const express = require('express');
const app = express();
// 模拟一个路由处理函数,可能会抛出错误
app.get('/error', (req, res, next) => {
const error = new Error('Something went wrong!');
error.status = 500; // 设置 HTTP 状态码
next(error); // 将错误传递给错误处理中间件
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack); // 记录错误堆栈
res.status(err.status || 500).json({
error: {
message: err.message
}
});
});
app.listen(3009, () => {
console.log('Server is running on port 3009');
});
启动服务器,在apipost工具中进行测试。
点击发送,得到结果
3、自定义错误对象
自定义错误对象可以帮助我们更清晰地表示特定类型的错误,并提供额外的上下文信息。
以下是一个自定义错误对象的简单代码示范。
const express = require('express');
const app = express();
// 自定义错误类
class CustomError extends Error {
constructor(message, status) {
super(message);
this.status = status;
this.name = 'CustomError';
}
}
// 模拟路由 1:抛出自定义错误
app.get('/custom-error', (req, res, next) => {
const error = new CustomError('Custom error occurred', 400);
next(error);
});
// 模拟路由 2:抛出普通错误
app.get('/error', (req, res, next) => {
const error = new Error('Something went wrong!');
error.status = 500;
next(error);
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(err.status || 500).json({
error: {
message: err.message,
name: err.name
}
});
});
app.listen(3009, () => {
console.log('Server is running on port 3009');
});
启动服务,打开apipost攻击进行测试
五、总结
至此,我们初步完成第一阶段的所有知识学习以及练习。多动手实践,举一反三,希望文章的案例会对大家有所帮助。
接下来的文章,我们接着第二阶段的知识学习以及代码案例练习。第二阶段的大纲如下:
第二阶段:进阶与应用
如果你喜欢这篇文章,请点赞收藏。
关注我,获取前端更多使用知识。
最近业务需求多,会比较忙,但我也会抽出时间进行更新文章,敬请期待。