Context 对象的组成与作用
Context 对象的组成与作用
Koa2框架中的Context对象是对Node.js原生请求和响应对象的封装,它提供了统一的API接口来简化Web开发。每次请求都会创建一个新的Context实例,贯穿整个中间件处理流程。
核心属性解析
Context对象包含以下主要属性:
- request:Koa的Request对象,封装了Node.js原生的http.IncomingMessage
- response:Koa的Response对象,封装了Node.js原生的http.ServerResponse
- app:应用实例引用
- state:推荐的命名空间,用于在中间件间传递信息
- cookies:用于处理cookie的便捷方法
app.use(async (ctx) => {
// 访问request对象
console.log(ctx.request.method);
// 访问response对象
ctx.response.status = 200;
// 使用state共享数据
ctx.state.user = await User.find(1);
// 操作cookies
ctx.cookies.set('name', 'value');
});
常用代理属性
Context对象代理了大量Request和Response的常用属性,可以直接通过ctx访问:
// Request代理属性示例
ctx.header // 等同于ctx.request.header
ctx.method // 等同于ctx.request.method
ctx.url // 等同于ctx.request.url
ctx.path // 等同于ctx.request.path
ctx.query // 等同于ctx.request.query
ctx.host // 等同于ctx.request.host
// Response代理属性示例
ctx.status // 等同于ctx.response.status
ctx.body // 等同于ctx.response.body
ctx.set // 等同于ctx.response.set
ctx.type // 等同于ctx.response.type
常用方法详解
1. throw方法
用于抛出HTTP错误:
ctx.throw(404, '资源不存在');
ctx.throw(400, '参数错误', { user: user.id });
2. assert方法
断言验证,不满足条件时抛出错误:
ctx.assert(ctx.state.user, 401, '请先登录');
ctx.assert(ctx.query.id, 400, '缺少ID参数');
3. redirect方法
实现页面重定向:
ctx.redirect('/login');
ctx.redirect('https://example.com');
4. attachment方法
设置文件下载:
ctx.attachment('report.pdf');
ctx.body = fs.createReadStream('/path/to/report.pdf');
请求处理相关
1. 获取请求参数
// 查询字符串 ?name=koa
ctx.query.name // "koa"
// POST请求体
const body = await parseBody(ctx);
// 动态路由参数
router.get('/user/:id', (ctx) => {
ctx.params.id // 123
});
2. 处理文件上传
const koaBody = require('koa-body');
app.use(koaBody({
multipart: true,
formidable: {
uploadDir: './uploads'
}
}));
app.use(async (ctx) => {
const file = ctx.request.files.file;
const reader = fs.createReadStream(file.path);
const stream = fs.createWriteStream(path.join('./uploads', file.name));
reader.pipe(stream);
});
响应处理相关
1. 设置响应头
ctx.set('Cache-Control', 'no-cache');
ctx.set({
'X-Powered-By': 'Koa',
'Author': 'Your Name'
});
2. 发送不同类型响应
// JSON响应
ctx.body = { success: true };
// HTML响应
ctx.type = 'html';
ctx.body = '<h1>Hello World</h1>';
// 流式响应
ctx.body = fs.createReadStream('./large-file.txt');
3. 自定义响应处理
app.use(async (ctx, next) => {
await next();
// 统一处理404
if (ctx.status === 404 && !ctx.body) {
ctx.status = 404;
ctx.body = '自定义404页面';
}
// 统一处理错误
if (ctx.status >= 400) {
ctx.app.emit('error', ctx.status, ctx);
}
});
状态管理
ctx.state是推荐的中间件间共享数据的命名空间:
// 认证中间件
app.use(async (ctx, next) => {
const token = ctx.headers['authorization'];
ctx.state.user = await verifyToken(token);
await next();
});
// 业务中间件
app.use(async (ctx) => {
const posts = await Post.findAll({
where: { userId: ctx.state.user.id }
});
ctx.body = posts;
});
高级用法
1. 自定义Context原型
可以扩展Context原型添加自定义方法:
app.context.db = require('./database');
app.use(async ctx => {
const users = await ctx.db.query('SELECT * FROM users');
ctx.body = users;
});
2. 请求/响应拦截
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
ctx.set('X-Response-Time', `${ms}ms`);
});
3. 内容协商
app.use(async (ctx) => {
ctx.response.vary('Accept');
switch (ctx.request.accepts('json', 'html')) {
case 'json':
ctx.type = 'json';
ctx.body = { data: '...' };
break;
case 'html':
ctx.type = 'html';
ctx.body = '<p>data</p>';
break;
default:
ctx.type = 'text';
ctx.body = 'data';
}
});
错误处理机制
Context对象集成了错误处理能力:
app.use(async (ctx, next) => {
try {
await next();
} catch (err) {
ctx.status = err.status || 500;
ctx.body = {
message: err.message,
code: err.code
};
ctx.app.emit('error', err, ctx);
}
});
// 触发错误
app.use(async (ctx) => {
if (!ctx.query.token) {
const error = new Error('Token required');
error.status = 401;
throw error;
}
});
性能优化技巧
1. 避免内存泄漏
// 错误示例:将大对象挂载到context
app.use(async (ctx) => {
ctx.hugeData = await getHugeData(); // 内存泄漏风险
});
// 正确做法
app.use(async (ctx) => {
const hugeData = await getHugeData();
ctx.body = processData(hugeData);
});
2. 合理使用流处理
app.use(async (ctx) => {
ctx.type = 'application/json';
ctx.body = database.query('SELECT * FROM large_table')
.stream()
.pipe(JSONStream.stringify());
});
3. 批量处理中间件
const compose = require('koa-compose');
const middleware1 = async (ctx, next) => { /* ... */ };
const middleware2 = async (ctx, next) => { /* ... */ };
app.use(compose([middleware1, middleware2]));
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:异步流程控制的实现方式