转载:https://segmentfault.com/a/1190000007792512
前两篇已经了解了yield和generator的相关概念,这篇文章继续分析Koa的源码,
Koa的用法,这里就不在列举了。我觉得Koa主要功能主要是下面几个方面
1). 提供了中间件机制
2). 封装了request/response,context对象
3). 使用了yield,提供了便利的流程控制,使异步编程更优雅
4). 便捷的异常处理,使用try catch就可以捕获程序中的异常,不需要考虑同步或者异步的问题
import koa from 'koa';
const app = koa();
app.experimental = true;
app.proxy = true;//当 app.proxy 设置为 true 时,支持 X-Forwarded-Host
//添加一个中间件
app.use(function*(next) {console.log('start'); yield *next; console.log('end'); })
app.listen(port);
koa会提供很多中间件,比如koa-router,koa-session,koa-bodyparse,koa-server等
var app = Application.prototype;module.exports = Application;
//函数的入口部分
function Application() {
if (!(this instanceof Application)) return new Application; this.env = process.env.NODE_ENV || 'development'; this.subdomainOffset = 2; this.middleware = []; this.proxy = false; this.context = Object.create(context); this.request = Object.create(request); this.response = Object.create(response); }
listen真正的创建了一个http server
app.listen = function(){
var server = http.createServer(this.callback()); return server.listen.apply(server, arguments); };
中间件use方法, fn必须是一个generator function, 可以通过'GeneratorFunction' == fn.constructor.name
app.use = function(fn){
if (!this.experimental) {
// so we have to make sure that `fn` is a generator function
assert(fn && 'GeneratorFunction' == fn.constructor.name, 'app.use() requires a generator function');
}
this.middleware.push(fn);
return this;
};
重要函数来啦,这里只是分析this.experimental = false的情况
app.callback = function(){ var fn = this.experimental ? compose_es7(this.middleware) : co.wrap(compose(this.middleware)); //co是使用的tj的co模块,这里先分析compose的函数用法 //compose 函数是将this.middleware数组的函数进行一个简单的处理,保证每个函数都有后一个函数的引用,具体代码看下面的分析 //co.wrap可以将一个generation function 进行转换,使fn能够自动运行 var self = this; if (!this.listeners('error').length) this.on('error', this.onerror); return function(req, res){ res.statusCode = 404; var ctx = self.createContext(req, res); onFinished(res, ctx.onerror); //这里执行中间件函数,然后将处理的结果都挂在ctx上,最后respond函数输出到前端,注意catch函数进行错误逻辑处理 fn.call(ctx).then(function () { respond.call(ctx); }).catch(ctx.onerror); } };
compose 代码分析, compse是将middleware里面的middleware都有下一个函数的引用
function compose(middleware){ return function *(next){ if (!next) next = noop(); var i = middleware.length; while (i--) { next = middleware[i].call(this, next); } return yield *next; } }
至此,koa的源码已经分析完毕了