ioioi
v1.0.8
Published
a middleware engine
Downloads
3
Readme
ioioi:洋葱模型执行引擎
ioioi仅仅提供一个洋葱模型的执行机制。无论是前端还是后端(Node.js)都可以基于此开发自己的应用。
其核心机制只有不到80行代码。ioioi利用 async 和 await 实现,现在的前后端都是完美支持的,请尽情使用。但是如果你要用在古老的项目上,请慎重!!
安装
npm i ioioi
详细说明
这不是一个开箱即用的工具,而是一个给需要造轮子的开发者使用的组件。一般来说,在开发中会经常需要分层处理以及通过组件灵活组合的情况,无论是操作系统还是web应用。
在众多的编程语言和开发框架以及各种成型的系统上,中间件、拦截器、钩子等名词经常会出现,它们本质上没有什么区别,为了让程序易于扩展、方便维护和定制。而且实现了组件或是模块的分离,还方便大家协作。
这个扩展主要还是专注于web领域,可以用于前端,也可以用在后端,因为其简单,没有涉及到任何前后端专有的东西。
使用
const ioioi = require('ioioi');
const ioi = new ioioi();
ioi.use(async (c, next) => {
console.log('m1 in');
await next();
console.log('m1 out');
});
ioi.use(async (c, next) => {
console.log('m2 in');
await next();
console.log('m2 out');
});
//run是async声明的函数,你可以用在try catch中捕获错误
ioi.run();
执行结果:
m1 in
m2 in
m2 end
m1 end
执行结果是按照洋葱模型的,只是遵循的是先添加先执行的原则,因为这样更符合编码逻辑。
在之前的示例上,没有对run传递参数,实际上,run是接收一个对象作为参数的。在web请求中,总是被称为请求上下文。不过在这里,你可以按照自己的设计执行。
run是async声明的函数,你可以用在try catch中捕获错误。
传递参数
const ioioi = require('ioioi');
function context() {
return {
method : '',
url : '',
path : '',
exec : null
};
}
const ioi = new ioioi();
ioi.use(async (c, next) => {
console.log('m1 in');
await next();
console.log('m1 out');
});
ioi.use(async (c, next) => {
console.log('m2 in');
await next();
console.log('m2 out');
});
//添加第三个中间件输出传递上下文对象的信息。
ioi.use(async (c, next) => {
console.log(c.method, c.url);
await next();
});
let ctx = context();
ctx.method = 'GET';
ctx.path = '/';
ctx.url = '/?name=home';
//如果传递参数对象存在属性exec并且是可执行函数,则会执行。
//并且把ctx自身作为参数传递。
ctx.exec = async (c) => {
console.log('我是最核心的应用,没有next。');
};
ioi.run(ctx);
输出结果:
m1 in
m2 in
GET /?name=home
我是最核心的应用,没有next。
m2 out
m1 out
如果传递参数对象存在属性exec并且是可执行函数,则会执行,并且会把ctx自身作为参数传递,你不必使用this来获取ctx。避免this指向错误带来的问题。
过滤执行
use原型如下:
use (midcall, filter = null) {
//...
}
使用use添加中间件,还支持第二个参数,默认为null。如果要起作用,则需要传递一个函数对象,其主要作用是对执行过程过滤,执行时,会把中间件接收到的参数传递过去,注意只有第一个参数传递,没有next。如果函数返回false则表示不通过,不会执行此中间件。
const ioioi = require('ioioi');
function context() {
return {
exec : null,
method : '',
pass : ''
};
}
let ioi = new ioioi();
let postCheck = (c) => {
if (c.method == 'POST' && c.pass !== 'abc') {
console.log(' post deny');
return false;
}
return true;
};
ioi.use(async (c, next) => {
console.log('m1 in');
await next();
console.log('m1 out');
});
ioi.use(async (c, next) => {
console.log(' m2 in');
await next();
console.log(' m2 out');
}, postCheck);
ioi.use(async (c, next) => {
console.log(' m3 in');
await next();
console.log(' m3 out');
});
let b = context();
b.method = 'POST';
b.pass = 'abcd';
b.exec = async (c) => {
console.log(' I am b');
};
ioi.run(b);
执行结果:
m1 in
post deny
m3 in
I am b
m3 out
m1 out
可以看到,中间件m2的输出没有执行,因为POST检测没有通过,函数返回false。如果你把pass改成abc,让postCheck检测通过,则会看到如下输出:
m1 in
m2 in
m3 in
I am b
m3 out
m2 out
m1 out
最后
简洁却极富表现力的功能,授之以渔。