Skip to content
On this page

Koa基础概念

Koa是一个轻量级的Web框架,通过利用async函数和中间件洋葱模型,提供了一种更优雅的方式来构建Web应用和API。理解Koa的基础概念是掌握这个框架的关键。

上下文(Context)对象

Koa将Node.js的request和response对象封装到单独的context对象中,称为ctx。

Context属性

javascript
app.use(async ctx => {
  // 请求相关属性
  ctx.request // Koa Request对象
  ctx.req     // Node.js原生request对象
  ctx.method  // HTTP方法 (GET, POST, PUT, DELETE等)
  ctx.url     // 完整URL
  ctx.path    // 路径部分
  ctx.query   // 查询参数对象
  ctx.params  // 路由参数
  ctx.headers // 请求头对象
  
  // 响应相关属性
  ctx.response // Koa Response对象
  ctx.res      // Node.js原生response对象
  ctx.body     // 响应体
  ctx.status   // 响应状态码
  ctx.type     // 响应内容类型
  ctx.length   // 响应长度
});

Context方法

javascript
app.use(async ctx => {
  // 设置响应
  ctx.body = 'Hello World';           // 设置响应体
  ctx.status = 200;                  // 设置状态码
  ctx.set('X-Custom-Header', 'value'); // 设置响应头
  ctx.redirect('/new-url');          // 重定向
  ctx.throw(400, 'Bad Request');     // 抛出错误
});

中间件(Middleware)

Koa的中间件使用async/await函数,形成了独特的洋葱模型:

javascript
// 洋葱模型示例
app.use(async (ctx, next) => {
  console.log('A - 进入');    // 1
  await next();              // 调用下一个中间件
  console.log('A - 退出');   // 5
});

app.use(async (ctx, next) => {
  console.log('B - 进入');    // 2
  await next();
  console.log('B - 退出');   // 4
});

app.use(async ctx => {
  console.log('C - 处理');    // 3
  ctx.body = 'Hello Koa';
});

中间件执行顺序

  1. 每个中间件函数执行到await next()时暂停
  2. 控制权交给下一个中间件
  3. 当没有更多中间件时,控制权反向传递
  4. 继续执行await next()之后的代码

请求(Request)对象

Koa对Node.js的原生request进行了增强:

javascript
app.use(async ctx => {
  // 基本信息
  ctx.request.method;     // HTTP方法
  ctx.request.url;        // URL
  ctx.request.origin;     // 协议+主机
  ctx.request.href;       // 完整URL
  
  // 头信息
  ctx.request.header;     // 所有请求头
  ctx.request.headers;    // 所有请求头(别名)
  ctx.request.length;     // 内容长度
  ctx.request.host;       // 主机名
  ctx.request.hostname;   // 不包含端口的主机名
  
  // 查询参数
  ctx.request.query;      // 解析后的查询参数
  ctx.request.querystring; // 原始查询字符串
  
  // 路径信息
  ctx.request.path;       // 路径
  ctx.request.search;     // 查询字符串(包含?)
  
  // 类型检查
  ctx.request.is('text/html');        // 检查内容类型
  ctx.request.accepts('html');        // 检查接受的类型
  ctx.request.acceptsCharsets('utf-8'); // 检查接受的字符集
  ctx.request.acceptsEncodings('gzip');  // 检查接受的编码
  ctx.request.acceptsLanguages('en-US'); // 检查接受的语言
});

响应(Response)对象

Koa对Node.js的原生response进行了增强:

javascript
app.use(async ctx => {
  // 设置响应
  ctx.response.body = 'Response';     // 设置响应体
  ctx.response.status = 200;         // 设置状态码
  ctx.response.message = 'OK';       // 设置状态消息
  ctx.response.length = 100;         // 设置响应长度
  
  // 设置头信息
  ctx.response.set('Content-Type', 'text/html');
  ctx.response.set({
    'X-Custom-Header': 'value',
    'Cache-Control': 'no-cache'
  });
  
  // 重定向
  ctx.response.redirect('/new-path');
  ctx.response.redirect('back');     // 重定向回referrer
  ctx.response.redirect('https://example.com'); // 外部重定向
  
  // 类型和内容
  ctx.response.type = 'json';        // 设置内容类型
  ctx.response.lastModified = new Date(); // 设置最后修改时间
  ctx.response.etag = '12345';       // 设置ETag
});

Koa的错误处理

Koa提供了层次化的错误处理机制:

javascript
const app = new Koa();

// 全局错误处理
app.on('error', (err, ctx) => {
  console.error('Server Error:', err);
  ctx.status = 500;
  ctx.body = { error: 'Internal Server Error' };
});

// 中间件内错误处理
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    ctx.status = err.status || 500;
    ctx.body = { error: err.message };
    console.error(err);
  }
});

Koa中间件模式

条件中间件

javascript
const conditionalMiddleware = async (ctx, next) => {
  if (ctx.path.startsWith('/api')) {
    // 只对API路径应用此中间件
    console.log('API request');
  }
  await next();
};

app.use(conditionalMiddleware);

参数化中间件

javascript
const createLogger = (prefix) => {
  return async (ctx, next) => {
    console.log(`${prefix}: ${ctx.method} ${ctx.path}`);
    await next();
  };
};

app.use(createLogger('[LOG]'));

应用(Application)对象

Koa应用对象是整个应用的入口:

javascript
const app = new Koa();

// 应用配置
app.proxy = true;           // 信任代理头
app.subdomainOffset = 2;    // 子域名偏移量
app.env = process.env.NODE_ENV || 'development'; // 环境

// 中间件注册
app.use(middleware);

// 服务器启动
const server = app.listen(3000, () => {
  console.log('Server running on port 3000');
});

// 事件监听
app.on('error', (err) => {
  console.error('Application error:', err);
});

app.on('close', () => {
  console.log('Server closed');
});

Koa与Express的比较

特性KoaExpress
异步处理原生支持async/await主要使用回调
中间件模型洋葱模型线性模型
核心大小更小较大
上下文统一的ctx对象分离的req/res
错误处理更好基础

洋葱模型详解

javascript
// 示例:洋葱模型的完整执行流程
const app = new Koa();

app.use(async (ctx, next) => {
  const start = Date.now();
  console.log('1. 开始处理请求');
  await next();  // 暂停并等待下游中间件完成
  const ms = Date.now() - start;
  console.log(`5. 请求处理完成, 耗时 ${ms}ms`);
  ctx.set('X-Response-Time', `${ms}ms`);
});

app.use(async (ctx, next) => {
  console.log('2. 记录请求信息');
  await next();
  console.log('4. 记录响应信息');
});

app.use(async ctx => {
  console.log('3. 处理业务逻辑');
  ctx.body = 'Hello Koa!';
});

这些基础概念构成了Koa框架的核心,为后续学习中间件系统、路由管理等高级特性打下了坚实基础.