内容简介:1、首先这是koa2最简单的入门例子,我将通过这个入门例子来演示koa2的洋葱模型在这里面,app首先是调用了两次use,然后就开始监听端口,因此use是核心:
分析
1、首先这是koa2最简单的入门例子,我将通过这个入门例子来演示koa2的洋葱模型
const Koa = require('koa');
const app = new Koa();
app.use((ctx,next)=>{
console.log("第一个中间件执行");
next() ;
});
// 第二个中间件
app.use((ctx,next)=>{
console.log("第二个中间件");
})
let r = app.listen(8080);
console.log("server run on 8080");
在这里面,app首先是调用了两次use,然后就开始监听端口,
listen(...args) {
debug('listen');
// 当客户端发送请求将会调用callback
const server = http.createServer(this.callback());
return server.listen(...args);
}
因此use是核心:
use(fn) {
// ... 一些判断代码
this.middleware.push(fn);
return this;
}
从上面可以看出这里将外部use的函数通过内部的一个middleware变量记录下来,然后就没了。
OK,现在当客户端发送请求的时候,内部会创建上下文对象,然后处理请求:
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;
}
处理请求
handleRequest(ctx, fnMiddleware) {
const res = ctx.res;
res.statusCode = 404;
const onerror = err => ctx.onerror(err);
const handleResponse = () => respond(ctx);
onFinished(res, onerror);
// 核心,调用中间件,从这里可以看出我们use(fn)中的fn是一个promise
return fnMiddleware(ctx).then(handleResponse).catch(onerror);
}
OK,到这里我们知道当浏览器发送一个请求的时候,koa的application对象会根据middleware调用compose来生成一个另一个函数fn,然后向fn中传入上下文ctx执行这个函数。我们都知道,最上面的代码执行顺序是先打印 第一个中间件执行
,再打印 第二个中间件执行
,那么这个compose这个函数就需要来保证这个机制。具体怎么实现看如下:
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!')
}
/**
* @param {Object} context
* @return {Promise}
* @api public
*/
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 = i
let fn = middleware[i]
if (i === middleware.length) fn = next
if (!fn) return Promise.resolve()
try {
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
} catch (err) {
return Promise.reject(err)
}
}
}
}
上面代码虽然不多,但是是koa2实现洋葱模型最重要的部分。整个过程如下:
- 客户端发送请求,调用fn(ctx),此时next为空=>dispatcher(0),获取第一次use的函数(middleware[0])执行这个函数,参数为:ctx、dispatch(1),这个dispatcher(1),也就是第一次use中的next;执行next();
- 在第一次use中的方法体中执行next()等价于执行dispatcher(1),此时获取第二次use的函数(middleware[1]),接着再执行这个函数,参数为:ctx、dispatch(2),以此类推执行后面的中间件.
总结
koa2源码虽然少,但是原理巧妙,值得学习,也正是因为它的小,对于w我们看源码学习也能更轻松.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 区块链安全性的洋葱模型
- 如何更好地理解中间件和洋葱模型
- KOA2 compose 串联中间件实现(洋葱模型)
- 主机安全:洋葱 Webshell 检测实践与思考
- koa2洋葱中学习async
- 【自定义View】洋葱数学同款雷达图深入解析-RadarView
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java Servlet & JSP Cookbook
Bruce W. Perry / O'Reilly Media / 2003-12-1 / USD 49.99
With literally hundreds of examples and thousands of lines of code, the Java Servlet and JSP Cookbook yields tips and techniques that any Java web developer who uses JavaServer Pages or servlets will ......一起来看看 《Java Servlet & JSP Cookbook》 这本书的介绍吧!