Skip to main content

koa2

koa2

koa2 和 express 的区别

  • 中间件模型
    • 洋葱 vs 线性(栈)
    • 会影响响应时机,express 会立即响应,koa2 需要等到中间件执行完毕
  • 异步方式,回调 vs 同步
  • 异常处理,error-first vs try-catch await
  • 代码体积

中间件

示例代码如下:

const Koa = require("koa");
const app = new Koa();

// x-response-time 中间件

app.use(async (ctx, next) => {
console.log("\n开始 x-response-time");
const start = Date.now();
await next(); // 调用下一个中间件:logger(等待下一个异步函数返回)
const ms = Date.now() - start;
ctx.set("X-Response-Time", `${ms}ms`); // 设置响应头
console.log("结束 x-response-time\n");
});

// logger 中间件

app.use(async (ctx, next) => {
console.log("开始 logger");
const start = Date.now();
await next(); // 调用下一个中间件:response(等待下一个异步函数返回)
const ms = Date.now() - start;
console.log(
`\u0020\u0020\u0020\u0020\u0020${ctx.method} ${ctx.url} - ${ms} ms`
); // \u0020 为空格
console.log("结束 logger");
});

// response 中间件

app.use(async (ctx) => {
console.log("开始 response");
ctx.body = "Hello World";
console.log("结束 response");
// 没有更多的中间件执行,堆栈将展开并且每个中间件恢复执行其上游行为
});

app.listen(3000);
console.log("app started at port 3000...");

如果一个中间件 没有调用 await next(),后续的 middleware 将不再执行了。例如,一个检测用户权限的 middleware 可以决定是否继续处理请求,还是直接返回 403 错误

app.use(async (ctx, next) => {
if (await checkUserPermission(ctx)) {
await next();
} else {
ctx.response.status = 403;
}
});

常见中间件实现

koa-cors

const URL = require("url");

module.exports = async function (ctx, next) {
let origin = URL.parse(ctx.origin) || "";
if (origin.protocol && origin.host) {
ctx.set(
"Access-Control-Allow-Origin",
`${origin.protocol}://${origin.host}`
);
ctx.set(
"Access-Control-Allow-Headers",
"X-Requested-With, User-Agent, Referer, Content-Type, Cache-Control, accesstoken"
);
ctx.set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
ctx.set("Access-Control-Max-Age", "86400");
ctx.set("Access-Control-Allow-Credentials", "true");
}
if (ctx.methods === "OPTIONS") {
ctx.status = 204;
ctx.body = "";
} else {
await next();
}
};