Koa
Koa初体验
___node.js的下一代web框架
- koa注册的中间件提供了两个参数:
- ctx:上下文(Context)对象;
- koa并没有像express一样,将req和res分开,而是将它们作为ctx的属性;
- ctx代表依次请求的上下文对象;
- ctx.request:获取请求对象;
- ctx.response:获取响应对象;
- next:本质上是一个dispatch,类似于之前的next;
1 | const Koa = require('koa'); |
Koa中间件
koa通过创建的app对象,注册中间件只能通过use方法:
Koa并没有提供methods的方式来注册中间件;
也没有提供path中间件来匹配路径;
但是真实开发中我们如何将路径和method分离呢?
方式一:根据request自己来判断;
方式二:使用第三方路由中间件;
Koa 路由
使用第三方库:npm install koa-router
- 封装user.router.js文件
- 在app中注册router.routes()为中间件
- 注意:allowedMethods用于判断某一个method是否支持:
- 如果我们请求 get,那么是正常的请求,因为我们有实现get;
- 如果我们请求 put、delete、patch,那么就自动报错:Method Not Allowed,状态码:405;
- 如果我们请求 link、copy、lock,那么就自动报错:Not Implemented,状态码:501;
参数解析
params - query
1 | const userRouter = new Router({prefix:'/users'}) |
json - urlencoded - form-data
解析json 和 x-www-form-urlencoded需要:
- 第三方库
const bodyParser = require('koa-bodyparser')
- 使用 koa-bodyparser的中间件
app.use(bodyParser())
解析:form-data
const multer = require('koa-multer')
const upload = multer()
app.use(upload.any())
1 | app.use((ctx,next)=>{ |
multer 文件上传处理
使用multer
1 | const uploadRouter = new Router({prefix:'/upload'}) |
koa数据响应
输出结果:body将响应主体设置为以下之一:
- string :字符串数据
- Buffer :Buffer数据
- Stream :流数据
- Object|| Array:对象或者数组
- null :不输出任何内容
- 如果response.status尚未设置,Koa会自动将状态设置为200或204(没有内容)。
1 | ctx.status = 200 |
源码中:
静态服务器
koa并没有内置部署相关的功能 所以使用第三方库 npm install koa-static
app.use(koaStatic('./build'))
错误处理方式
通过发出事件 接收事件
1 | app.use((ctx,next)=>{ |
koa源码
创建koa
开启监听
中间件的注册
- 监听回调
在之前的写多个中间件只执行最后一个的原因就是源码中handleRequest中 return fnMiddleware(ctx).then(handleResponse).catch(onerror);
- compose
Koa和express的对比
### 从架构设计上
- express 完整且强大 其中帮助我们内置了很多好用的功能
- koa是简洁自由的 只包含最核心的功能 不会对使用其他中间件限制
- 需要通过路由或者自己判断请求方式或者其他功能
- express和koa框架他们的核心都是中间件
- 但是他们的中间件执行机制不同,特别针对某个中间件包含异步操作时
两者中间件的执行顺序对比
案例:
假如有三个中间件在一次请求中匹配到 并且按照顺序执行
希望实现的方案是:
- 在middleware1 中,在req.message中添加一个字符串aaa
- 在middleware2 中,在req.message中添加一个字符串bbb
- 在middleware3中,在req.message中添加一个字符串ccc
- 当所有内容添加结束 在middleware1中 通过res 返回最终的结果
express实现
- 同步数据
1 | const express = require('express') |
源码中首先主动调用了一次next() 遇到了next后继续匹配 然后匹配到middleware2 之后执行middleware2 的next 执行到了middleware3以后逐步回到middleware1 所以返回的结果是 aaabbbcc
- 异步数据
1 | const express = require('express') |
结果是aaabbb 并不会有请求的结果 如果想要有结果的话那么把res.end()写在 middleware3里面请求的后面 或者不把middleware3 当作一个中间件 而是在middleware1中把 middleware3当作一个函数调用才能实现
koa实现
- 同步数据
1 | const Koa = require('koa'); |
- 异步
1 | const Koa = require('koa'); |
在koa中 实现next 返回的是一个Promise 而 express是一个普通同步函数 所以可以在koa中使用 async await 来实现异步操作
koa洋葱模型
两层理解含义:
- 中间件处理代码的过程
- Response返回body执行
request时执行到最后 然后再一层一层往外执行
如果express所有的操作都是同步的也是符合洋葱模型的 但是不能有异步的