// 接下来我们还需要用来格式化参数的装饰器
export function Parse(type) {
return (target, name, index) => {
parseList.push({
target,
type,
method: name,
index
})
}
}
// 以及最后我们要处理的各种参数的获取
export function Param(position) {
return (key) => (target, name, index) => {
paramList.push({
target,
key,
position,
method: name,
index
})
}
}
export const Body = Param('body')
export const Header = Param('header')
export const Cookie = Param('cookie')
export const Query = Param('query')
export const Get = Method('get')
export const Post = Method('post')
Koa服务的处理
上边是创建了所有需要用到的装饰器,但是也仅仅是把我们所需要的各种信息存了起来,而怎么利用这些装饰器则是下一步需要做的事情了:
const routers = []
// 遍历所有添加了装饰器的Class,并创建对应的Router对象
routerList.forEach(item => {
let { basename, constrcutor } = item
let router = new Router({
prefix: basename
})
controllerList
.filter(i => i.target === constrcutor.prototype)
.forEach(controller => {
router[controller.type](controller.path, async (ctx, next) => {
let args = []
// 获取当前函数对应的参数获取
paramList
.filter( param => param.target === constrcutor.prototype && param.method === controller.method )
.map(param => {
let { index, key } = param
switch (param.position) {
case 'body': args[index] = ctx.request.body[key] break
case 'header': args[index] = ctx.headers[key] break
case 'cookie': args[index] = ctx.cookies.get(key) break
case 'query': args[index] = ctx.query[key] break
}
})
// 获取当前函数对应的参数格式化
parseList
.filter( parse => parse.target === constrcutor.prototype && parse.method === controller.method )
.map(parse => {
let { index } = parse
switch (parse.type) {
case 'number': args[index] = Number(args[index]) break
case 'string': args[index] = String(args[index]) break
case 'boolean': args[index] = String(args[index]) === 'true' break
}
})
// 调用实际的函数,处理业务逻辑
let results = controller.controller(...args)
ctx.body = results
})
})
routers.push(router.routes())
})
const app = new Koa()
app.use(bodyParse())
app.use(compose(routers))
app.listen(12306, () => console.log('server run as :12306'))
上边的代码就已经搭建出来了一个Koa的封装,以及包含了对各种装饰器的处理,接下来就是这些装饰器的实际应用了:
import { Router, Get, Query, Parse } from "../decorators"
@Router('')
export default class {
@Get('/')
index (@Parse('number') @Query('id') id: number) {
return {
code: 200,
id,
type: typeof id
}
}
@Post('/detail')
detail (
@Parse('number') @Query('id') id: number,
@Parse('number') @Body('age') age: number
) {
return {
code: 200,
age: age + 1
}
}
}