前言
Koa 是一个精致小巧的基于 Node.js 的 Web 框架。目前有 1.x
和 2.x
2 个大的版本
其中 2.x
版本使用了 Node.js v7.6.0 之后支持的 async await
语法糖,提供了更优雅的异步编程模式。
Koa 有如下特点:
- 内核精简,不内置中间件. 小巧但富有表现力。
- 类似栈的方式运行中间件,Koa 调用下游,然后堆栈展开再将控制再流回上游。简单实用
- 实用async await或generator避免了callback hell
- 优雅的异常捕获
Koa 通过上面的机制避免了以往 connect 等实现的一些问题,例如要实现一个耗时统计时需要将 startTime 层层传递到末尾中间件。Koa 与 express 和 connect 的差别如下:
为了一探 Koa 的全貌,我们基于 Koa 1.x 的版本来开始学习之旅(主要是为了学习generator,其他方面1和2其实原理是一样的)。后面计划的教程如下:
- 开端。安装和启动
- 常用中间件
- 错误处理和最佳实践
- 开发并部署一个 todo-list 应用
- 升级为 Koa2
- 初探 Koa 源码
安装
使用 Koa 搭建一个 Web 应用是极其简单的。Koa 模块暴露了一个 Application 的 class 给 Web 开发者,我们只需实例化这个 Application,并给它注入适当的 请求和响应处理逻辑
. 实际上,整个 Koa 应用的开发模式就是如此简单。
下面是步骤:
- 进入我们的项目目录,安装 Koa
# 初始化 package.json
npm init
# 安装 Koa 1.x
npm i koa@1 -d
- 在我们的项目目录创建一个 index.js 文件,用于编写 Web 站点的主要逻辑
const Koa = require('koa')
const app = new Koa() // 实例化一个 Koa 应用
app.listen(3000) // 让 Koa 启动内置 server
这样应用便启动了,并监听了本机的 3000 端口。 实际上 http server 也可以不由 Koa 来启动,你可以导出 Koa 的handler,配合自己的 TSW 或 其他 Server 来使用:
const server = http.createServer(app.callback())
server.listen(3000)
上面的代码目前还没有任何的请求处理逻辑。Koa 是通过给 application 注入中间件函数的方式来注入 业务逻辑。
中间件
Koa的中间件很像Express的中间件,也是对HTTP请求进行处理的函数,但是必须是一个Generator函数。而且,Koa的中间件是一个级联式(Cascading)的结构,也就是说,属于是层层调用,第一个中间件调用第二个中间件,第二个调用第三个,以此类推。上游的中间件必须等到下游的中间件返回结果,才会继续执行,这点很像递归
从中间件的执行流程可以看出,第一个被执行的中间件,其也会在最后再次回到该中间件并执行剩下的代码逻辑。
Koa 的中间件依次执行来处理接收的 requests 并响应一个 response。每一个中间件都能访问到 context 对象,这是一个封装了原生 Node 请求和响应的对象,并提供了许多开发 web 应用和 API 有用的方法。在 Koa 1 里面,每个中间件就是一个 Generator 函数,我们看这个例子:
const Koa = require('koa')
const app = new Koa() // 实例化一个 Koa 应用
// 日志中间件
const mylogger = function *(next) {
yield next
// 在 Koa1版本 的Generator中间件函数中,this表示context对象
const rt = this.response.get('X-Respnose-Time')
console.log(`${this.method} ${this.url} - ${rt}`)
}
// x-response-time 中间件
const mytime = function *(next) {
const start = Date.now()
yield next
const ms = Date.now() - start
this.set('X-Response-Time', `${ms}ms`)
}
// 业务逻辑
const mylogic = function *(next) {
this.body = 'hello koa 1'
}
app.use(mylogger)
app.use(mytime)
app.use(mylogic)
app.listen(3000) // 让 Koa 启动内置 server
这个例子里,给 Koa 传入了 3 个中间件,每个中间件是个 Koa1.x 支持的 Generator 函数。基于 Generator 的支持,我们可以在里面书写异步代码,使用 yield 来暂停函数的执行。
基于首个中间件内 Generator 异步的调用,整个 Koa 中间件相当于被卷入一个栈中,并形成如下的调用顺序:
| ↑
| |
| |
| |
↓ |
在控制台,我们可以看到打印出了一次请求的耗时。
GET / - 1ms
学习思路
学习 Koa, 其实就是学习 Koa 的 4 个对象:
- Application 类型的实例属性和方法(主要用作 Web 应用的设置和启动)
- context 上下文对象, 它是包裹了 Node.js 的 http request 和 response 对象, 同时又提供了 Koa 的一些方法和属性供开发者使用
- Koa request 对象。这个便是 context.request(Koa 1 里面是 this.request) ,是 Koa 为了开发方便提供的一些跟 http 请求相关的方法
- Koa response 对象。这个便是 context.response(Koa 1 里面是this.response),是 Koa 为了开发方便提供的跟 http 响应有关的方法
因此实际上我们可以简单理解为,编写中间件代码时,只需要学习一个对象: context。context 对象会在 Koa 接收到任意一个请求后,执行中间件之前初始化,并传递给中间件。它有如下几个必要的属性:
- request:指向Request对象
- response:指向Response对象
- req:指向Node的request对象
- res:指向Node的response对象
- app:指向App对象
- state:用于在中间件传递信息。
更多的属性和方法文档,直接参考官网好了
路由
Koa 核心不携带任何中间件,路由也是。后面我们会介绍路由中间件的原理和用法。
视图渲染
Koa 核心不包含任何模板引擎的支持,如果需渲染视图,我们需要引入相应的视图中间件。
总结
Koa 提供了比 express 更精简的内核,类似 connect 的中间件机制,更 fasion 的异步流程控制方法(1.x 是 generator 2.x 是 async 语法)。兼具精简、高效、灵活性,是个优秀和值得学习的框架
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。