Koa
通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。
基本使用
- 需先建对象与 express 不同:const app = new Koa()
- ctx(context)封装了 res 和 req
- 返回使用 ctx.body,可使用 async 和 await
- ctx.body 最终会转换为 res.end
- 执行时机:洋葱模型的最外层,第一个中间件 promise 有结果后,将 ctx.body 转换为 res.end()
- 异步使用时,不可放置异步函数中,需放置在 await 的 promise 中
- 也可直接使用 ctx.res 和 ctx.req
- 常用属性:req、res、request、response
- 返回使用 ctx.body,可使用 async 和 await
- ctx 属性:
1 | const Koa = require("koa"); // ⼀个类 |
中间件(洋葱模型)
使用 app.use,回调函数只能传一个,多个需多次注册
异步流程会等待后续中间件有结果时返回
在 koa 中,中间件被 next() 方法分成了两部分。next() 方法上面部分会先执行,下面部门会在后续中间件执行全部结束之后再执行。
- 多个中间件会形成一个栈结构(middlestack),以"先进后出"(first-in-last- out)的顺序执行。
- 最外层的中间件首先执行。
- 调用 next 函数,把执行权交给下一个中间件。
- 最内层的中间件最后执行。
- 执行结束后,把执行权交回上一层的中间件。
- 最外层的中间件收回执行权之后,执行 next 函数后面的代码.
1 | app.use(async function (ctx, next) { |
与 express 比较
框架 | express | koa |
---|---|---|
模型 | 线性模型 | 洋葱模型 |
表现 | 同步表现为洋葱模型,但遇到异步,即使使⽤了 await next()也不会等待,会继续向下执⾏,因为 next()返回 undefined | ⽆论同步,还是异步,都是洋葱模型,可以使⽤ await 和 next() 来等待下⼀个中间件执⾏完成 |
原理 | 使⽤回调, next(),返回 undefined | next(),返回 promise,会把中间件⽤ promise 包裹起来 |
错误 | 错误处理是在⼀个特殊签名的中间件中完成的,它必须被添加到链的后⾯才能捕获到前⾯的错误 | 可以使⽤ try catch 捕获中间件错误 |
注意 | await next() 也不会等待下⼀个中间件异步完成 | 要使⽤ await 来等待异步操作;注意 res.end 的时机,等最外层的中间件(也就是第⼀个中间件)的 promise 有结果后,响应就会被返回 ctx.body ->res.end(ctx.body) |
中间件编写
1 | //编写⼀个计算请求的时⻓的中间件 |
错误处理
在最顶层捕获未处理的错误
1 | // 可以使⽤try catch 捕获中间件错误 |
- stack 是数组,收集了多个 async 函数,即返回值是 promise,内部有异步,总之就是收集了所有的异步操作;
- compose 是核心代码,函数接收 stack 数组返回一个匿名函数(这里采用了闭包);
- 核心代码就是执行这个匿名函数;
我们来看下 compose 函数:
1 | function compose(middleware) { |
Context(上下文)
Koa Context 将 node 的 request 和 response 对象封装到单个对象中,为编写 Web 应用程序和 API 提供了许多有用的方法。
1 | app.use(async (ctx) => { |
为方便起见许多上下文的访问器和方法直接委托给它们的 ctx.request 或 ctx.response ,不然的话它们是相同的。 例如 ctx.type 和 ctx.length 委托给 response 对象,ctx.path 和 ctx.method 委托给 request。
ctx.req
Node 的 request 对象.
ctx.res
Node 的 response 对象.
绕过 Koa 的 response 处理是 不被支持的. 应避免使用以下 node 属性:
- res.statusCode
- res.writeHead()
- res.write()
- res.end()
别名
Request 别名
以下访问器和 Request 别名等效:
- ctx.header
- ctx.headers
- ctx.method
- ctx.method=
- ctx.url
- ctx.url=
- ctx.originalUrl
- ctx.origin
- ctx.href
- ctx.path
- ctx.path=
- ctx.query
- ctx.query=
- ctx.querystring
- ctx.querystring=
- ctx.host
- ctx.hostname
- ctx.fresh
- ctx.stale
- ctx.socket
- ctx.protocol
- ctx.secure
- ctx.ip
- ctx.ips
- ctx.subdomains
- ctx.is()
- ctx.accepts()
- ctx.acceptsEncodings()
- ctx.acceptsCharsets()
- ctx.acceptsLanguages()
- ctx.get()
Response 别名
以下访问器和 Response 别名等效:
- ctx.body
- ctx.body=
- ctx.status
- ctx.status=
- ctx.message
- ctx.message=
- ctx.length=
- ctx.length
- ctx.type=
- ctx.type
- ctx.headerSent
- ctx.redirect()
- ctx.attachment()
- ctx.set()
- ctx.append()
- ctx.remove()
- ctx.lastModified=
- ctx.etag=