寫一個簡易中間件

目的

解決項目中代碼耦合度比較高,能夠隨時對業務部分代碼進行插拔。數組

API 設計

applyMiddleWare(middleWares) //middleWares 傳入的中間件app

返回值 fn //fn 爲啓動中間件的方法ide

支持複合調用 applyMiddleWare(middleWare1, applyMiddleWare(middleWares), .....)測試

實現

咱們假定有三個中間件:add, substract, multiplyspa

順序是 add -> substract -> multiply設計

單箇中間件的設計是:code

function MiddleWare(next) => {
    return function(str){
        next(str)
    }
    
}
複製代碼

next爲下一個啓動中間件的方法,思路其實很簡單,就是把multiply 的 裏面一層即 function(str){ next() } 這一層做爲substract 的next,再依次往上掛,因此咱們能夠寫下以下代碼cdn

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記錄組合的中間件的,例如:blog

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);
複製代碼

結果

相關文章
相關標籤/搜索