一:簡介
koa是基于nodejs平臺(tái)的下一代web框架(官網(wǎng)描述)
官網(wǎng)地址:https://koa.bootcss.com/
git地址:https://github.com/koajs/koa.git
koa提供基于http服務(wù)的最簡的框架模型涎显,包括洋蔥式的中間件處理邏輯占哟、對(duì)請(qǐng)求和響應(yīng)的封裝等硬贯。
二:使用
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下共四個(gè)文件:application.js澳厢,context.js耘眨,request.js扰魂,response.js
3.1 application.js
application.js是暴露給外部的入口肃叶,關(guān)鍵代碼:
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方法接收中間件(即函數(shù)),并將其放入middleware數(shù)組中茁帽;
return this玉罐,用于支持use的鏈?zhǔn)秸{(diào)用;
3.1.2 listen
listen(...args) {
debug('listen');
const server = http.createServer(this.callback());
return server.listen(...args);
}
koa提供的服務(wù)潘拨,本質(zhì)上是nodejs的http模塊提供的吊输。koa定義了自己的callback函數(shù)用來接收請(qǐng)求和返回結(jié)果;
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函數(shù)是koa-compose提供的铁追,其作用是將多個(gè)中間件整理成一個(gè)中間件季蚂,在此中間件內(nèi)部,原來的多個(gè)中間件的執(zhí)行過程是洋蔥式的;
createContext的作用是封裝req,res為一個(gè)context對(duì)象扭屁,該對(duì)象經(jīng)handleRequest函數(shù)傳入每一個(gè)中間件透硝;
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);
}
當(dāng)所有中間件執(zhí)行完畢,調(diào)用handleResponse函數(shù)疯搅,來返回結(jié)果
3.2 context.js
包含createContext的返回對(duì)象相關(guān)的一些方法
3.3 request.js
基于http.createServer中callback內(nèi)的參數(shù) req,封裝了一些方法
3.4 response.js
基于http.createServer中callback內(nèi)的參數(shù) res埋泵,封裝了一些方法
四:最簡實(shí)現(xiàn)
假設(shè)不考慮參數(shù)驗(yàn)錯(cuò)幔欧,req和res封裝等,最簡的類koa模型應(yīng)該具備以下特征
- 支持增加中間件
- 中間件的執(zhí)行流程為洋蔥式
- context傳入每個(gè)中間件丽声,以實(shí)現(xiàn)中間件間的數(shù)據(jù)共享
- 具備處理各種事件的能力礁蔗,如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);
}
}