Koa 是一个非常轻量的 web 开发框架,由 Express 团队打造。相较于 Express,Koa 使用 async 函数解决异步的问题,并且完全脱离中间件,非常优雅,而且 Koa 代码简洁友好,很适合初学者阅读。
可以看到 Koa 的结构非常简单,lib 文件夹下面放着 koa 的核心文件:
application 是 koa 的入口文件,export 出一个 Application 的类(继承自 events.Emitter)。application 有以下几个主要(public)的 api:
_
开头)的对象。module.exports = class Application extends Emitter {
listen(...args) {
debug('listen');
const server = http.createServer(this.callback());
return server.listen(...args);
}
use(fn) {
if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
this.middleware.push(fn);
return this;
}
callback() {
const fn = compose(this.middleware);
if (!this.listenerCount('error')) this.on('error', this.onerror);
const handleRequest = (req, res) => {
const ctx = this.createContext(req, res);
return this.handleRequest(ctx, fn);
};
return handleRequest;
}
}
context 是我们在使用 koa 中最常接触到的 ctx,就是一个暴露出来的对象。context 中实现了对 cookie 的 get set 操作,这也是我们可以直接使用 ctx 对 cookie 操作的原理。除此之外,ctx 中最重要的是 delegate,也就是委托。我们简单看一下代码:
delegate(proto, 'response')
.method('attachment')
.method('redirect')
.method('remove')
.method('vary')
.method('set')
.method('append')
.method('flushHeaders')
.access('status')
.access('message')
.access('body')
.access('length')
.access('type')
.access('lastModified')
.access('etag')
.getter('headerSent')
.getter('writable');
以上的 proto 就是 ctx,实现了对 response 对象的代理,比如我们可以通过使用 ctx.status 来访问 ctx.response.status。
同样的,request 上面的属性和方法也被代理到了 ctx 中:
delegate(proto, 'request')
.method('acceptsLanguages')
.method('acceptsEncodings')
.method('acceptsCharsets')
.method('accepts')
.method('get')
.method('is')
.access('querystring')
.access('idempotent')
.access('socket')
.access('search')
.access('method')
.access('query')
.access('path')
.access('url')
.access('accept')
.getter('origin')
.getter('href')
.getter('subdomains')
.getter('protocol')
.getter('host')
.getter('hostname')
.getter('URL')
.getter('header')
.getter('headers')
.getter('secure')
.getter('stale')
.getter('fresh')
.getter('ips')
.getter('ip');
ctx.hostname 即是 ctx.request.hostname。
request.js 和 response.js 中完成对 Koa Request/Response 对象的封装,可以通过 request.xxx/response.xxx 对其进行操作。其中使用了很多 get 和 set 方法。