🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 应用 Koa 应用是一个包含一系列中间件 generator 函数的对象。 这些中间件函数基于 request 请求以一个类似于栈的结构组成并依次执行。 Koa 类似于其他中间件系统(比如 Ruby's Rack 、Connect 等), 然而 Koa 的核心设计思路是为中间件层提供高级语法糖封装,以增强其互用性和健壮性,并使得编写中间件变得相当有趣。 Koa 包含了像 content-negotiation(内容协商)、cache freshness(缓存刷新)、proxy support(代理支持)和 redirection(重定向)等常用任务方法。 与提供庞大的函数支持不同,Koa只包含很小的一部分,因为Koa并不绑定任何中间件。 任何教程都是从 hello world 开始的,Koa也不例外^_^ ``` var koa = require('koa'); var app = koa(); app.use(function *(){ this.body = 'Hello World'; }); app.listen(3000); ``` ## 中间件级联 Koa 的中间件通过一种更加传统(您也许会很熟悉)的方式进行级联,摒弃了以往 node 频繁的回调函数造成的复杂代码逻辑。 我们通过 generators 来实现“真正”的中间件。 Connect 简单地将控制权交给一系列函数来处理,直到函数返回。 与之不同,当执行到 `yield next` 语句时,Koa 暂停了该中间件,继续执行下一个符合请求的中间件('downstrem'),然后控制权再逐级返回给上层中间件('upstream')。 下面的例子在页面中返回 "Hello World",然而当请求开始时,请求先经过 `x-response-time` 和 `logging` 中间件,并记录中间件执行起始时间。 然后将控制权交给 `reponse` 中间件。当中间件运行到 `yield next` 时,函数挂起并将控制前交给下一个中间件。当没有中间件执行 `yield next` 时,程序栈会逆序唤起被挂起的中间件来执行接下来的代码。 ``` var koa = require('koa'); var app = koa(); // x-response-time app.use(function *(next){ var start = new Date; yield next; var ms = new Date - start; this.set('X-Response-Time', ms + 'ms'); }); // logger app.use(function *(next){ var start = new Date; yield next; var ms = new Date - start; console.log('%s %s - %s', this.method, this.url, ms); }); // response app.use(function *(){ this.body = 'Hello World'; }); app.listen(3000); ``` ## 配置 应用配置是 `app` 实例属性,目前支持的配置项如下: * `app.name` 应用名称(可选项) * `app.env` 默认为 **NODE_ENV** 或者 `development` * `app.proxy` 如果为 `true`,则解析 "Host" 的 header 域,并支持 `X-Forwarded-Host` * `app.subdomainOffset` 默认为2,表示 `.subdomains` 所忽略的字符偏移量。 ## app.listen(...) Koa 应用并非是一个 1-to-1 表征关系的 HTTP 服务器。 一个或多个Koa应用可以被挂载到一起组成一个包含单一 HTTP 服务器的大型应用群。 如下为一个绑定3000端口的简单 Koa 应用,其创建并返回了一个 HTTP 服务器,为 `Server#listen()` 传递指定参数(参数的详细文档请查看[nodejs.org](http://nodejs.org/api/http.html#http_server_listen_port_hostname_backlog_callback))。 ``` var koa = require('koa'); var app = koa(); app.listen(3000); ``` `app.listen(...)` 实际上是以下代码的语法糖: ``` var http = require('http'); var koa = require('koa'); var app = koa(); http.createServer(app.callback()).listen(3000); ``` 这意味着您可以同时支持 HTTPS 和 HTTPS,或者在多个端口监听同一个应用。 ``` var http = require('http'); var koa = require('koa'); var app = koa(); http.createServer(app.callback()).listen(3000); http.createServer(app.callback()).listen(3001); ``` ## app.callback() 返回一个适合 `http.createServer()` 方法的回调函数用来处理请求。 您也可以使用这个回调函数将您的app挂载在 Connect/Express 应用上。 ## app.use(function) 为应用添加指定的中间件,详情请看 [Middleware](https://github.com/koajs/koa/wiki#middleware) ## app.keys= 设置签名Cookie密钥,该密钥会被传递给 [KeyGrip](https://github.com/jed/keygrip)。 当然,您也可以自己生成 `KeyGrip` 实例: ``` app.keys = ['im a newer secret', 'i like turtle']; app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256'); ``` 在进行cookie签名时,只有设置 `signed` 为 `true` 的时候,才会使用密钥进行加密: ``` this.cookies.set('name', 'tobi', { signed: true }); ``` ## 错误处理 默认情况下Koa会将所有错误信息输出到 stderr,除非 **NODE_ENV** 是 "test"。为了实现自定义错误处理逻辑(比如 centralized logging),您可以添加 "error" 事件监听器。 ``` app.on('error', function(err){ log.error('server error', err); }); ``` 如果错误发生在 请求/响应 环节,并且其不能够响应客户端时,`Contenxt` 实例也会被传递到 `error` 事件监听器的回调函数里。 ``` app.on('error', function(err, ctx){ log.error('server error', err, ctx); }); ``` 当发生错误但仍能够响应客户端时(比如没有数据写到socket中),Koa会返回一个500错误(Internal Server Error)。 无论哪种情况,Koa都会生成一个应用级别的错误信息,以便实现日志记录等目的。