1.简介
koa框架是一个遵循洋葱模型的轻量级的nodejs框架,将大部分工作都抛给中间件来处理,框架只专注于compose各个中间件,并按照use注册的顺序逐个执行中间件。
2.安装使用
安装:npm install koa -s
使用:
const Koa = require('koa');
const app = new Koa;
app.listen(3000);
3.中间件的使用
const Koa = require('koa');
const mount = require('koa-mount');
const app = new Koa();
app.use(mount('/api', function() {
.....
}));
app.listen(80);
以上代码使用了koa-mount来进行进行路由处理,使用koa实例上的use方法将mount函数返回的函数注册为中间件。以下是koa中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函数中先是判断是否为generator函数,如果是,使用koa-convert转换,最终都会放入koa实例的middleware数组中保存,供后续调用。
a.说一下isGeneratorFunction
函数,这个函数的思路是通过Function
动态创建一个generate函数,然后取其原型与传入的函数的原型对比,如果相同说明传入函数就是generate函数。
b.再说一下convert
函数,这个函数在koa-convert
包中,就是内部又引入了co
库,将传入的generate函数包裹,达到自执行的效果。
回过头说一下koa的listen函数,代码如下:
listen(...args) {
debug('listen');
const server = http.createServer(this.callback());
return server.listen(...args);
}
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;
}
可以看到,listen函数内部调用了node核心模块http,创建了一个http服务,并将自身的callback函数作为http服务的响应函数。
而callback函数内部则是通过compose将之前注册的中间件包裹,然后通过createContext将req和res封装到一个ctx中,逐层传入后面的中间件中。ctx内容如下:
4.request和response处理
如上所示,req和res被封装到了context中,在各个中间件都可以从参数中得到,中间件可以拿到两个参数:一个是context,各中间件可以通过它来进行通信和同步状态;第二个是next,调用它会执行后续中间件。使用示例如下:
const Koa = require('koa')
const app = new Koa()
//声明一个main中间件,如果你急于了解中间件可以跳转到(三)
const main = (ctx,next) =>{
if (ctx.request.accepts('json')) {
ctx.response.type = 'json';
ctx.response.body = { data: 'Hello World' };
} else if (ctx.request.accepts('html')) {
ctx.response.type = 'html';
ctx.response.body = 'Hello World
';
} else if (ctx.request.accepts('xml')) {
ctx.response.type = 'xml';
ctx.response.body = 'Hello World';
} else{
ctx.response.type = 'text';
ctx.response.body = 'Hello World';
};
}; //直接运行页面中会显示json格式,因为我们没有设置请求头,所以每一种格式都是ok的。
app.use(main)//app.use()用来加载中间件。
app.listen(3000)
可以看到,我们给返回数据赋值可以直接使用’=‘赋值,在koa的response中body通过set属性,将设置进来的body值按照其type进行处理,如下。
set body(val) {
const original = this._body;
this._body = val;
// no content
if (null == val) {
if (!statuses.empty[this.status]) this.status = 204;
if (val === null) this._explicitNullBody = true;
this.remove('Content-Type');
this.remove('Content-Length');
this.remove('Transfer-Encoding');
return;
}
// set the status
if (!this._explicitStatus) this.status = 200;
// set the content-type only if not yet set
const setType = !this.has('Content-Type');
// string
if ('string' === typeof val) {
if (setType) this.type = /^\s* this.ctx.onerror(err));
// overwriting
if (null != original) this.remove('Content-Length');
}
if (setType) this.type = 'bin';
return;
}
// json
this.remove('Content-Length');
this.type = 'json';
},
5.静态资源
使用koa-static中间件来处理静态资源,实例如下:
安装npm: npm install koa-static
使用:
const Koa = require('koa');
const app = new Koa();
const path = require('path');
const serve = require('koa-static');
const main = serve(path.join(__dirname));
app.use(main);
app.listen(3000);
参考资料:
https://zhuanlan.zhihu.com/p/67239164?utm_id=0