创建一个简单的应用
// 1、实例化app
var Koa = require('koa');
const app = new Koa();
// 2、声明中间件函数
async function responseTime(ctx, next) {
const start = new Date();
await next();
const ms = new Date() - start + 10;
ctx.set('X-Response-Time', `${ms}ms`);
}
async function responseContent(ctx, next) {
if ('/' != this.url) return;
ctx.body = 'Hello World!';
}
// 3、使用中间件
app.use(responseTime);
app.use(responseContent);
// 4、应用监听端口
app.listen(3000);
app对象
const Emitter = require('events');
class Application extends Emitter {
constructor() {
super();
this.proxy = false;
// 用于存储中间件
this.middleware = [];
this.subdomainOffset = 2;
this.env = process.env.NODE_ENV || 'development';
// 上下文
this.context = Object.create(context);
this.request = Object.create(request);
this.response = Object.create(response);
}
}
app.use()添加中间件时做了什么
use(fn) {
// 省略fn判断
this.middleware.push(fn);
return this;
}
app.listen(3000)监听端口
listen() {
const server = http.createServer(this.callback());
return server.listen.apply(server, arguments);
}
callback() {
// 返回一个用于dispatch中间件的函数,默认从index = 0开始
const fn = compose(this.middleware);
if (!this.listeners('error').length) this.on('error', this.onerror);
return (req, res) => {
res.statusCode = 404;
// 使用请求和响应对象创建上下文对象
const ctx = this.createContext(req, res);
onFinished(res, ctx.onerror);
// 执行中间件函数并响应
fn(ctx).then(() => respond(ctx)).catch(ctx.onerror);
};
}
function compose (middleware) {
if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')
for (const fn of middleware) {
if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
}
// 提供公开api用于调度中间件函数
return function (context, next) {
// last called middleware #
let index = -1
return dispatch(0)
function dispatch (i) {
if (i <= index) return Promise.reject(new Error('next() called multiple times'))
// 改变变量index
index = i
// 取出当前中间件
let fn = middleware[i]
if (i === middleware.length) fn = next
if (!fn) return Promise.resolve()
try {
return Promise.resolve(fn(context, function next () {
//触发下一中间件执行
return dispatch(i + 1)
}))
} catch (err) {
return Promise.reject(err)
}
}
}
}
// 创建上下文对象
createContext(req, res) {
const context = Object.create(this.context);
const request = context.request = Object.create(this.request);
const response = context.response = Object.create(this.response);
context.app = request.app = response.app = this;
context.req = request.req = response.req = req;
context.res = request.res = response.res = res;
request.ctx = response.ctx = context;
request.response = response;
response.request = request;
context.onerror = context.onerror.bind(context);
context.originalUrl = request.originalUrl = req.url;
context.cookies = new Cookies(req, res, {
keys: this.keys,
secure: request.secure
});
context.accept = request.accept = accepts(req);
context.state = {};
return context;
}
思维导图