目的
解决项目中代码耦合度比较高,可以随时对业务部分代码进行插拔。
API 设计
applyMiddleWare(middleWares) //middleWares 传入的中间件
返回值 fn //fn 为启动中间件的方法
支持复合调用 applyMiddleWare(middleWare1, applyMiddleWare(middleWares), .....)
实现
我们假定有三个中间件:add, substract, multiply
顺序是 add -> substract -> multiply
单个中间件的设计是:
function MiddleWare(next) => {
return function(str){
next(str)
}
}
复制代码
next为下一个启动中间件的方法,思路其实很简单,就是把multiply 的 里面一层即 function(str){ next() } 这一层作为substract 的next,再依次往上挂,所以我们可以写下如下代码
function applyMiddleWare(middleWares){
var next = function(str){
return str;
};
middleWares = middleWares.reverse();
for(var i=0; i<middleWares.length; i++){
var next = middleWares[i](next);
}
return next;
}
」
复制代码
至于最里面的那一层没有next,我们又是从后往前遍历中间件,所以入口的next 返一个 var next = function(str){ return str;}这个就好了,把处理的结果抛上去。
至于middleware复合的情况会有一点复杂,我们举个例子: applyMiddleWare(middleWare1, applyMiddleWare(middleWares)) middleWare1 的结构是 (next) => (str) => {}, applyMiddleWare(middleWares)的结构是 (str) => {}。我比较偷懒,打算把所有的组合都作为普通中间件,这里用了一个contents记录组合的中间件的,例如:
var start = applyMiddleWare(middleWares1, middleWares2, middleWares3);
那么start的contents 就是[middleWares1, middleWares2, middleWares3],对于组合和非组合的用content字段区别,统一展开,类似数组展平,具体实现如下:
function add(next){
return function (str){
console.log('add中间件before(准备+2):', str);
str += 2;
str = next(str);
console.log('add中间件after:', str);
return str;
}
}
function subtract(next){
return function(str){
console.log('subtract中间件before(准备-1):', str);
str -= 1;
str = next(str);
console.log('subtract中间件after:', str);
return str;
}
}
function multiply(next){
return function(str){
console.log('multiply中间件before(准备*2):', str);
str *= 2;
str = next(str);
console.log('multiply中间件after:', str);
return str;
}
}
function flattenMiddleWare(middleWares){
var _array = [];
for(var i=0; i<middleWares.length; i++){
if(middleWares[i].isContents){
_array.push(...flattenMiddleWare(middleWares[i].isContents))
}else{
_array.push(middleWares[i]);
}
}
return _array;
}
function applyMiddleWare(middleWares){
var next = function(str){
return str;
};
middleWares = flattenMiddleWare(middleWares).reverse();
for(var i=0; i<middleWares.length; i++){
var next = middleWares[i](next);
}
next.isContents = middleWares;
return next;
}
function extraDivideMiddle(next){
return function(str){
console.log('divide中间件before(准备/0.5):', str);
str /= 0.5;
str = next(str);
console.log('divide中间件after:', str);
return str;
}
}
//测试
var result = applyMiddleWare([extraDivideMiddle, applyMiddleWare([add, subtract, multiply]), extraDivideMiddle])(10);
console.log('result:', result);
复制代码