一:简介
koa是基于nodejs平台的下一代web框架(官网描述)
官网地址:https://koa.bootcss.com/
git地址:https://github.com/koajs/koa.git
koa提供基于http服务的最简的框架模型,包括洋葱式的中间件处理逻辑、对请求和响应的封装等。
二:使用
const Koa = require('koa');
let koa = new Koa();
koa.use((ctx, next) => {
console.log(ctx.request.url);
ctx.body = { code: 200, success: true };
});
koa.listen(5000);
console.log('server listen 5000');
三:源码
源码的lib下共四个文件:application.js,context.js,request.js,response.js
3.1 application.js
application.js是暴露给外部的入口,关键代码:
3.1.1 use
use(fn) {
if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
if (isGeneratorFunction(fn)) {
deprecate('Support for generators will be removed in v3. ' +
'See the documentation for examples of how to convert old middleware ' +
'https://github.com/koajs/koa/blob/master/docs/migration.md');
fn = convert(fn);
}
debug('use %s', fn._name || fn.name || '-');
this.middleware.push(fn);
return this;
}
use方法接收中间件(即函数),并将其放入middleware数组中;
return this,用于支持use的链式调用;
3.1.2 listen
listen(...args) {
debug('listen');
const server = http.createServer(this.callback());
return server.listen(...args);
}
koa提供的服务,本质上是nodejs的http模块提供的。koa定义了自己的callback函数用来接收请求和返回结果;
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;
}
compose函数是koa-compose提供的,其作用是将多个中间件整理成一个中间件,在此中间件内部,原来的多个中间件的执行过程是洋葱式的;
createContext的作用是封装req,res为一个context对象,该对象经handleRequest函数传入每一个中间件;
handleRequest(ctx, fnMiddleware) {
const res = ctx.res;
res.statusCode = 404;
const onerror = err => ctx.onerror(err);
const handleResponse = () => respond(ctx);
onFinished(res, onerror);
return fnMiddleware(ctx).then(handleResponse).catch(onerror);
}
当所有中间件执行完毕,调用handleResponse函数,来返回结果
3.2 context.js
包含createContext的返回对象相关的一些方法
3.3 request.js
基于http.createServer中callback内的参数 req,封装了一些方法
3.4 response.js
基于http.createServer中callback内的参数 res,封装了一些方法
四:最简实现
假设不考虑参数验错,req和res封装等,最简的类koa模型应该具备以下特征
- 支持增加中间件
- 中间件的执行流程为洋葱式
- context传入每个中间件,以实现中间件间的数据共享
- 具备处理各种事件的能力,如error事件
'use strict';
const Emitter = require('events');
const http = require('http');
const compose = require('koa-compose');
class SimpleKoa extends Emitter{
constructor() {
super();
this.middleware = [];
}
use(fn) {
this.middleware.push(fn);
return this;
}
listen(...args) {
const server = http.createServer(this.callback());
server.listen(...args);
}
callback() {
if (!this.listenrCount('error')) this.on('error', (error) => console.error(error));
let fn = compose(this.middleware);
const handleRequest = (req, res) => {
let ctx = {
req,
res
};
return this.handleRequest(ctx, fn);
}
return handleRequest;
}
handleRequest(ctx, fnMiddleware) {
return fnMiddleware(ctx);
}
}