「这是我参与2022首次更文挑战的第21天,活动详情查看:2022首次更文挑战」
koa框架和express的核心都是中间件。
初体验:
const koa = require("koa");
const app = new koa();
app.use((ctx, next) => {
console.log(ctx.request);
ctx.response.body = "你好";
});
app.listen(8000, () => {
console.log("服务器启动成功");
});
koa中间件
特点:
- 只能通过use来创建中间件。
- Koa没有提供methods的方式来注册中间件
- 没有提供path中间件来匹配路径
- 也不能在一个use中注册多个中间件
因此我们需要自己来判断路径和请求方法,也可以使用路由来实现。
第三方库路由
由于koa中没有给我们提供path和方法中间件,因此我们可以通过路由的方式来实现不同的请求方式和不同路径的请求。
安装第三方库:koa-router
npm install koa-router
首先创建一个路由文件,编写不同的请求方式,然后在入口文件中注册路由,完成使用。
allowedMethods用于判断某一个method是否支持:
如果我们请求 get,那么是正常的请求,因为我们有实现get;
如果我们请求 put、delete、patch,那么就自动报错:
Method Not Allowed,状态码:405;
如果我们请求 link、copy、lock,那么久自动报错:
Not Implemented,状态码:501;
//user.js
const Router = require("koa-router");
const UserRouter = new Router({prefix: "/user"});
UserRouter.get("/", (ctx, next) => {
ctx.response.body = "get请求成功";
});
UserRouter.post("/", (ctx, next) => {
ctx.response.body = "psot请求成功";
});
module.exports = UserRouter;
//index.js
const koa = require("koa");
const UserRouter = require("./user");
const app = new koa();
app.use(UserRouter.routes());
//
app.use(allowedMethods());
app.listen(8000, () => {
console.log("服务器启动成功");
});
参数解析
解析params和query
UserRouter.get("/:id", (ctx, next) => {
console.log(ctx.params);
ctx.response.body = "get请求成功";
});
UserRouter.post("/", (ctx, next) => {
console.log(ctx.query);
ctx.response.body = "psot请求成功";
});
koa-bodyparser插件
koa-bodyparser默认支持的是form 和json格式的数据。可以通过设置enableTypes来添加解析类型。
//enableTypes的默认值为['text','form']
app.use(bodyParser({enableTypes: ["text", "json","form"]}));
通过ctx.request.body来获取请求body中的数据。可以解析jison,text,x-www-form-urlencoded等。
UserRouter.post("/", (ctx, next) => {
console.log(ctx.request.body);
ctx.response.body = "psot请求成功";
});
koa-body
koa-body也可以用来解析数据
支持解析:
- multipart/form-data
- application/x-www-urlencoded
- application/json
- application/json-patch+json
- application/vnd.api+json
- application/csp-report
- text/xml
解析text,json,x-www-urlencoded,
const Koa = require('koa');
const koaBody = require('koa-body');
const app = new Koa();
app.use(koaBody());
app.use(ctx => {
ctx.body = `Request Body: ${JSON.stringify(ctx.request.body)}`;
});
app.listen(3000);
解析form-data需要配置参数
app.use(koaBody({multipart: true}));//接受form表单数据
文件上传
通过路由实现文件上传,配置koaBody中的参数实现文件的上传。
const Router = require("koa-router");
const koaBody = require("koa-body");
const LoginRouter = new Router({prefix: "/login"});
LoginRouter.post(
"/",
koaBody({
multipart: true,
formidable: {
// 设置上传文件大小最大限制,默认2M
maxFileSize: 200 * 1024 * 1024,
//保存的路径
uploadDir: "./",
//是否保持原扩展
keepExtensions: true,
onFileBegin: (name, file) => {
//设置上传后的文件名
file.path = "one.md";
},
},
}),
(ctx, next) => {
//获取文件信息
console.log(ctx.request.files);
ctx.body = "post-login请求成功";
}
);
module.exports = LoginRouter;
koa-multer
koa-multer可以用来解析form-data,和上传文件。
上传文件案例: 上传文件案例:
//user.js
const Router = require("koa-router");
const path = require("path");
const multer = require("koa-multer");
const UserRouter = new Router({prefix: "/user"});
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "./uploads");
},
filename: (req, file, cb) => {
cb(null, Date.now() + path.extname(file.originalname));
},
});
const upload = multer({
storage,
});
//解析所有类型的数据
UserRouter.use(upload.any());
UserRouter.get("/:id", (ctx, next) => {
console.log(ctx.params);
ctx.response.body = "get请求成功";
});
//注意只能通过ctx.req来获取数据,ctx.request获取不到数据
UserRouter.post("/", upload.single("file"), (ctx, next) => {
console.log(ctx.req.file);
ctx.response.body = "psot请求成功";
});
module.exports = UserRouter;
相应数据类型
string :字符串数据
Buffer :Buffer数据
Stream :流数据
Object|| Array:对象或者数组
null :不输出任何内容
如果response.status尚未设置,Koa会自动将状态设置为200或204、
静态服务器
koa-static第三方库可以实现部署静态资源。
下载koa-static
npm install koa-static
const Koa = require('koa');
const staticAssets = require('koa-static');
const app = new Koa();
app.use(staticAssets('./build'));
app.listen(8000, () => {
console.log("koa初体验服务器启动成功~");
});
异常处理
const koa = require("koa");
const app = new koa();
app.use((ctx, next) => {
//发射错误
ctx.app.emit("error", new Error("异常fee"), ctx);
ctx.response.body = "请求成功";
});
//监听错误
app.on("error", (err, ctx) => {
console.log(err.message);
ctx.response.body = "哈哈哈";
});
app.listen(8000, () => {
console.log("服务器启动成功");
});
express和koa的比较
express的功能比较全面,内置了很多库。但是koa没有内置其他的库文件,是比较纯净的,更加轻量级。
最本质的区别是中间件的架构不同,express是同步的执行,而koa是可以处理异步行为的。
koa中的next()函数返回的是一个promise,因此我们可以用来处理异步请求,当中间件存在异步的请求时,我们可以等到异步数据请求成功后再执行后面得之后的代码。
例如:这个例子中会等到result中得到结果后,我们才会响应ctx.body数据。
const Koa = require('koa');
const axios = require('axios');
const app = new Koa();
const middleware1 = async (ctx, next) => {
ctx.message = "aaa";
await next();
ctx.body = ctx.message;
}
const middleware2 = async (ctx, next) => {
ctx.message += "bbb";
await next();
}
const middleware3 = async (ctx, next) => {
const result = await axios.get('http://123.207.32.32:9001/lyric?id=167876');
ctx.message += result.data.lrc.lyric;
}
app.use(middleware1);
app.use(middleware2);
app.use(middleware3);
app.listen(8000, () => {
console.log("服务器启动成功~");
})
洋葱模型
洋葱模型中的每一层都代表一个中间件,用于实现不同的功能,每次请求都会左侧最外层开始执行,直到执行到最里层时,完成最里层的执行,然后向外层卓层返回。因此如果当我们需要response数据时,应该在调用next()函数之后来返回数据,不然不能得到完整的结果。