2

前言

Koa 是一个精致小巧的基于 Node.js 的 Web 框架。目前有 1.x2.x 2 个大的版本

其中 2.x 版本使用了 Node.js v7.6.0 之后支持的 async await 语法糖,提供了更优雅的异步编程模式。

Koa 有如下特点:

  • 内核精简,不内置中间件. 小巧但富有表现力。
  • 类似栈的方式运行中间件,Koa 调用下游,然后堆栈展开再将控制再流回上游。简单实用
  • 实用async await或generator避免了callback hell
  • 优雅的异常捕获

Koa 通过上面的机制避免了以往 connect 等实现的一些问题,例如要实现一个耗时统计时需要将 startTime 层层传递到末尾中间件。Koa 与 express 和 connect 的差别如下:

express koa 对比

为了一探 Koa 的全貌,我们基于 Koa 1.x 的版本来开始学习之旅(主要是为了学习generator,其他方面1和2其实原理是一样的)。后面计划的教程如下:

  1. 开端。安装和启动
  2. 常用中间件
  3. 错误处理和最佳实践
  4. 开发并部署一个 todo-list 应用
  5. 升级为 Koa2
  6. 初探 Koa 源码

安装

使用 Koa 搭建一个 Web 应用是极其简单的。Koa 模块暴露了一个 Application 的 class 给 Web 开发者,我们只需实例化这个 Application,并给它注入适当的 请求和响应处理逻辑. 实际上,整个 Koa 应用的开发模式就是如此简单。

下面是步骤:

  1. 进入我们的项目目录,安装 Koa
# 初始化 package.json
npm init
# 安装 Koa 1.x
npm i koa@1 -d
  1. 在我们的项目目录创建一个 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 语法)。兼具精简、高效、灵活性,是个优秀和值得学习的框架


sheldon
947 声望1.6k 粉丝

echo sheldoncui


引用和评论

0 条评论