文章目录
Koa入门
Koa.js是一款微型Web框架,写一个hello world很简单,但web应用离不开session,视图模板,路由,文件上传,日志管理。这些 Koa 都不提供,需要自行去官方的 Middleware 寻找。然而,100个人可能找出100种搭配--引用自其他博主
一. koa起步
1 项目初始化
执行npm init -y
生成package.json
npm init -y
2 按照koa
执行 npm install koa
安装
npm install koa
3 编写服务程序
- 导入koa包
const Koa = require('Koa')
- 实例化app对象
const app = new Koa()
- 启动服务
app.listen(端口号, ()=>{})
// 导入Koa包
const Koa = require('koa')
// 实例化app对象
const app = new Koa()
// 编写中间件
app.use((ctx)=> {
// ctx: content http请求上下文
ctx.body = 'hello koa'
})
// 启动服务
app.listen(3000, ()=> {
console.log('server is running at http://127.0.0.1:3000')
})
二. 中间件
1 基本概念
1.1 什么事中间件
中间件,就是在请求和响应中间的处理函数
有时候,从请求到响应的业务比较复杂,或者有些业务要单独抽离出来,每次请求都要调用,减少代码量,这些单独抽离出来的一个个功能独立的函数,就是中间件
中间件就像流水线上的工人,每个人干不同的工作,A干完传递给B,B干完传递给C…
1.2 基本使用
next
交由下一个中间件
ctx.body
向客户端相应的数据
const Koa = require('koa')
const app = new Koa()
app.use((ctx, next)=>{
console.log('我是中间件1')
next()
})
app.use((ctx, next)=>{
console.log('我是中间件2')
next()
})
app.use((ctx, next)=>{
console.log('我是中间件3')
ctx.body = 'hello koa'
})
app.listen(3001, ()=> {
console.log('server is running at http://127.0.0.1:3001')
})
1.3 链式调用
上面的代码还可以写成
const Koa = require('koa')
const app = new Koa()
app.use((ctx, next)=>{
console.log('我是中间件1')
next()
})
.use((ctx, next)=>{
console.log('我是中间件2')
next()
})
.use((ctx, next)=>{
console.log('我是中间件3')
ctx.body = 'hello koa'
})
app.listen(3001, ()=> {
console.log('server is running at http://127.0.0.1:3001')
})
2 洋葱圈模型
图片引自其他博主
const Koa = require('koa')
const app = new Koa
app.use((ctx, next)=> {
console.log(1)
next()
console.log(2)
})
app.use((ctx, next)=> {
console.log(3)
next()
console.log(4)
})
app.use((ctx, next)=> {
console.log(5)
ctx.body = 'hello koa'
})
app.listen(3000, ()=> {
console.log('server is running at http://127.0.0.1:3000')
})
上面代码的输入结果为 :1 3 5 4 2
原理:
- 执行第一个中间件,输出1,执行next(),执行下一个中间件
- 执行第二个中间件,输出3,执行next(),执行下一个中间件
- 执行第三个中间件,输出5,执行完
ctx.body = 'hello koa'
,第三个中间件执行完毕 - 第三个中间件执行完毕,等同于,第二个中间件的next(),执行完毕,第二个中间件继续向下执行,输出4,此时,第二个中间件执行完毕。
- 第二个中间件执行完毕,等同于,第一个中间件next(),执行完毕,第一个中间件件继续向下执行,输出2,此时所有中间件都执行完毕了。
- 因此,依次输出 1 3 5 4 2 ,这就是洋葱圈模型,先由外向内执行,再由内向外执行。
补充
express 也符合洋葱圈模型,依次输出 1 3 5 4 2
const express = require('express')
const app = express()
app.use((req, res, next)=> {
console.log('1')
next()
console.log('2')
})
app.use((req, res, next)=> {
console.log('3')
next()
console.log('4')
})
app.use((req, res, next)=> {
console.log('5')
res.send('hello express')
})
app.listen(3001, ()=> {
console.log(console.log('server is running at http://127.0.0.1:3001'))
})
3 异步处理
const Koa = require('koa')
const app = new Koa()
app.use(async(ctx, next)=> {
ctx.data = 'hell'
await next()
})
app.use(async(ctx, next)=> {
ctx.data += 'o K'
await next()
})
app.use(async(ctx, next)=> {
const res = await Promise.resolve('oa')
ctx.body = ctx.data += res
})
app.listen(3000, ()=> {
console.log('server is running at http://127.0.0.1:3000')
})
三. 路由
1 什么是路由
- 建立URL和处理函数之间的对应关系
- 根据不同的Method和URL返回不同的内容
const Koa = require('koa')
const app = new Koa()
app.use(ctx=> {
if(ctx.request.url === '/') {
ctx.response.body = '这是主页'
} else if(ctx.request.url === '/users') {
if(ctx.request.method === 'GET') {
console.log(1111)
ctx.response.body = '通过get请求访问的'
} else if(ctx.request.method === 'POST') {
ctx.response.body = '通过post请求访问的'
}
} else {
ctx.response.body = '404'
}
})
app.listen(3000, ()=> {
console.log('server is running at http://127.0.0.1:3000')
})
ctx.resquest.url
可简写为 ctx.url
ctx.resquest.method
可简写为 ctx.method
ctx.response.body
可简写为 ctx.body
2 使用koa-router
2.1 安装
npm i koa-router
2.2 使用
const Koa = require('koa')
// 引入koa-router
const Router = require('koa-router')
const app = new Koa()
// 实例化koa-router
const router = new Router()
// 编写路由函数
router.get('/list', (ctx)=> {
ctx.body = ctx
})
router.post('/info', (ctx)=> {
ctx.body = ctx
})
// 注册路由
app.use(router.routes())
app.listen(3000, ()=> {
console.log('server is running at http://127.0.0.1:3000')
})
2.3 优化
将router抽离出来,模块化开发
src
目录下新增router
文件,在改文件夹下新增两个文件users.router.js
和role.router.js
------------------index.js
----------------------
const Koa = require('koa')
const app = new Koa()
const userRouter = require('./router/users.router.js')
const roleRouter = require('./router/role.router.js')
app.use(userRouter.routes())
app.use(roleRouter.routes())
app.listen(3000, ()=> {
console.log('server is running at http://127.0.0.1:3000')
})
------------------users.router.js
----------------------
const Router = require('koa-router')
const router = new Router()
const baseUrl = '/users'
const getRealUrl = (url)=> {
return baseUrl + url
}
router.get(getRealUrl('/list'), (ctx)=> {
ctx.body = `通过${ ctx.method }方式请求,请求地址为${ ctx.url }`
})
router.post(getRealUrl('/add'), (ctx)=> {
ctx.body = `通过${ ctx.method }方式请求,请求地址为${ ctx.url }`
})
module.exports = router
------------------role.router.js
----------------------
const Router = require('koa-router')
const router = new Router()
const baseUrl = '/role'
const getRealUrl = (url)=> {
return baseUrl + url
}
router.get(getRealUrl('/list'), (ctx)=> {
ctx.body = `通过${ ctx.method }方式请求,请求地址为${ ctx.url }`
})
router.post(getRealUrl('/add'), (ctx)=> {
ctx.body = `通过${ ctx.method }方式请求,请求地址为${ ctx.url }`
})
module.exports = router
四. 请求参数解析
1 get动态路由参数
通过ctx.params
来获取
const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
const router = new Router()
router.get('/list/:id', (ctx)=> {
ctx.body = ctx.params
})
app.use(router.routes())
app.listen(3000, ()=> {
console.log('server is running at http://127.0.0.1:3000')
})
2 get请求参数
通过ctx.query
来获取
const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
const router = new Router()
router.get('/info', (ctx)=> {
ctx.body = ctx.query
})
app.use(router.routes())
app.listen(3000, ()=> {
console.log('server is running at http://127.0.0.1:3000')
})
通过ctx.throw(异常状态码)
返回异常状态码
3 post请求参数
- 安装
koa-body
中间件
npm i koa-body
- 注册
koa-body
const Koa = require('koa')
const app = new Koa()
const koaBody = require('koa-body')
app.use(koaBody)
示例代码
const Koa = require('koa')
const Router = require('koa-router')
const koaBody = require('koa-body')
const app = new Koa()
const router = new Router()
app.use(koaBody())
router.post('/add', (ctx)=> {
ctx.body = ctx.request.body
})
app.use(router.routes())
app.listen(3000, ()=> {
console.log('server is running at http://127.0.0.1:3000')
})
五. 错误处理
1 原生错误
404
:没有找到对应路由,或者对应路由没有通过ctx.body
进行返回,koa
会自动返回404
- 通过
ctx.throw(400)
手动抛出异常 - 500:代码错误,koa会自动返回500
2 错误级别中间件
- 安装
npm i koa-json-error
- 使用
const error = require('koa-json-error')
app.use(error())
// 或者自定义格式
app.use(error(
function formatError(err) {
return {
status: err.status,
message: err.message
}
}
))
示例代码
const Koa = require('koa')
const Router = require('koa-router')
const koaBody = require('koa-body')
const koaError = require('koa-json-error')
const app = new Koa()
const router = new Router()
app.use(koaBody())
router.post('/add', (ctx)=>{
// ctx.body = ctx.request.body
ctx.throw(400, '参数错误')
})
// app.use(koaError())
app.use(koaError(
function formatError(err) {
return {
status: err.status,
message: err.message
}
}
))
app.use(router.routes())
app.listen(3000, ()=> {
console.log('server is running at http://127.0.0.1:3000')
})