跳至主要內容

Context上下文

微信公众号:储凡About 9 min

Context上下文

在客户端/服务器端发生数据交互时,Node.jsrequest对象、response对象应用非常频繁。 在Koa框架中,Context上下文就是将 request对象、response对象进行封装。为编写Web应用程序、API时提供很多、很方便的方法

对于每个客户端请求,Koa框架都会创建一个Context上下文对象,在请求的处理流程中,作为中间件的参数引用,一般用ctx表示,例如:

app.use(ctx => {
  // Context对象
  console.log(ctx)
  // Koa的Request对象
  console.log(ctx.request)
  // Koa的Response对象
  console.log(ctx.response)
})

为方便起见,许多上下文的访问器和方法直接委托给它们的 ctx.request对象或 ctx.response对象 ,不然的话它们是相同的。 例如:

  • ctx.typectx.length 委托给 response 对象
  • ctx.pathctx.method 委托给 request 对象

API方法

ctx.req和ctx.request

Node的request对象,包含客户端请求的详细信息

ctx.res和ctx.response

Noderesponse对象,包含服务端响应的详细信息,需要注意的是:绕过koaresponse统一处理是不被支持的。

避免使用:

  • res.statusCode
  • res.writeHead()
  • res.write()
  • res.end()

例如:

app.use(async(ctx, next) => {
  ctx.body = 'hello world'
  ctx.status = 200
  ctx.res.statusCode = 500
})

ctx.state

推荐的命名空间,可以将信息传递到中间件或者前端视图,例如:

// 从DB中查询用户信息
const userInfo=await User.findAll()
// 将用户信息绑在state上
ctx.state.userInfo=userInfo

ctx.app

上下文中的app对象,是对应用程序实例的引用,例如:

const app=new Koa()

app.use(ctx=>{
  // ctx.app是对app的引用,返回true
  console.log(ctx.app === app)
})

ctx.cookies

服务端关于Cookie的使用,挂载到Context上下文中,可以实现对Cookie的操作,查看源码:

利用Cookies包进行管理,将Cookies对象挂在到Context对象中

设置Cookie信息

ctx.cookies.set('name',"142vip")
// 支持options可选参数
ctx.cookies.set('web',"142vip.cn",{})

获取Cookie信息

const name =ctx.cookies.set('name')
// 支持options可选参数
const webInfo=ctx.cookies.set('web',{})

实质上是基于cookies模块实现的,可以查看Cookies APIopen in new window

ctx.throw

用来抛出指定错误码的错误,结合全局中间件可以对抛出的错误进行全局捕获,然后分类处理。 同样,对于Koa框架程序抛出错误 如果没有中间件去处理错误,框架层面也能对部分错误码做处理。

抛错方式:

ctx.throw(400)
ctx.throw(400, '参数错误');
ctx.throw(400, '参数错误', { message:'缺少必要参数' });

ctx.throw其实是对http-errors模块的一层封装,当你使用ctx.throw(400, '参数错误')时,等价于:

// 定义错误信息
const error = new Error('参数错误');
error.status = 400;
error.expose = true;
// 抛错
throw error;

注意,这是用户级错误,并用 err.expose 标记,这意味着消息适用于客户端响应。 通常不是错误的详细内容,因为服务端不应该把故障详细信息返回给客户端。

ctx.assert

类似与node 的 assert() 方法,可以用来程序断言,例如:

// 断言ctx.state.user是否为空
ctx.assert(ctx.state.user, 401, 'User not found. Please login!');

语法格式如下:

  • ctx.assert(value, [status], [msg], [properties])

value值判断为!value,非真,抛出状态码为status、错误信息为msg的错误。

实质上,ctx.assert是封装http-assert来实现的,详细用法可以参考:http-assert APIopen in new window

更多

Context对象的可用API还是非常多的,具体可以参考:Context APIopen in new window

一些实践

const Koa = require('koa')
const app = new Koa()
app.use(async(ctx, next) => {
  // Context对象
  console.log(ctx)
  // Koa的Request对象
  console.log(ctx.request)
  // Koa的Response对象
  console.log(ctx.response)

  await next()
})

app.use(ctx => {
  // ctx.app是对app的引用
  console.log(ctx.app === app)
  ctx.cookies.set()
  ctx.throw(400)
  ctx.throw(400, '参数错误')
  ctx.throw(400, '参数错误', { message: '缺少必要参数' })

  ctx.assert()
})


app.use(async(ctx, next) => {
  ctx.body = 'hello world'
  ctx.status = 200
  ctx.res.statusCode = 500
})


app.listen(8000)
console.log('listening on port 8000')