Koa2+Ts扩展Content
问题
在 koa2 中,我们通常会使用 context.body 来返回数据
ts
route.post('/login', async (context: Context) => {
const res = {
data: {},
code: 200,
msg: 'success'
}
context.response.type = 'application/json'
context.body = res
})
但是这样很显然是不合理的,因为每次的返回数据结构都是不可控的,所以需要统一返回数据的方法和数据结构
目标
- 1、扩展 Content
- 2、统一接口数据结构
- 3、类型定义文件扩展
解决
定义数据结构
ts
/**
* 接口响应体
*/
export interface IResponse {
code?: number
message?: string
success?: boolean
serverTime?: number
data?: any
}
扩展Content
同样的,我们在 content
中定义新的方法,然后统一返回数据结构
为了区分,成功使用 success
,失败使用 fail
我们将这个操作放在中间件中去维护,其实就是一个 function
ts
/**
* @author: forguo
* @description: rest
*/
import { Context, Next } from 'koa'
import { IResponse } from '@/types/response'
// 处理请求成功方法
const render = (context: Context) => {
// 返回一个 function
return ({ code = 200, message = 'success', data }: IResponse) => {
context.response.type = 'application/json'
const response: IResponse = {
code,
message,
success: code.toString().startsWith('2'),
serverTime: Date.now()
}
if (data) {
response.data = data
}
context.body = response
}
}
// 处理请求失败方法
const renderFail = (ctx: Context) => {
// 返回一个 function
return ({ code = -1, message = 'error', data }: IResponse) => {
ctx.success({
code,
message,
data
})
}
}
export default () => {
return async (context: Context, next: Next) => {
// 返回一个 function,在 controller 中执行
context.success = render(context)
context.fail = renderFail(context)
await next()
}
}
中间件集成
ts
import { Context, Next } from 'koa'
import compose from 'koa-compose'
import koaBody from 'koa-body'
import json from 'koa-json'
import rest from './rest'
const app = new Koa()
/**
* 使用koa-compose 集成中间件
*/
const middleware = compose([
// ...其他中间件
json(),
koaBody(),
rest(),
// ...其他中间件
])
app.use(middleware)
中间件集成完成,也就完成了 context.success
和 context.fail
的扩展
这里也可以在错误处理中去集成 context.fail
使用
ts
route.post('/login', async (context: Context) => {
const res = {
data: {},
code: 200,
msg: 'success'
}
context.success(res)
})
类型定义文件扩展
由于我们是扩展 npm 包,所以需要使用 declare module 'koa'
ts
/**
* 扩展 koa Context,ts 会自动融合类型
*/
import { IResponse } from '@/types/response'
export * from 'koa'
declare module 'koa' {
/**
* 添加 success 和 fail 方法
*/
interface Context {
/**
* 响应成功
* @param data 响应数据
*/
success: (data: IResponse) => void
/**
* 响应失败
* @param data
*/
fail: (data: IResponse) => void
}
}
这样就可以愉快的使用 context.success
和 context.fail
了,并且是有类型提示和 ts 错误提示的