详解中间件

中间件(Middleware)是软件开发中一种常见的设计模式,其核心思想是‌在核心逻辑的执行过程中插入可扩展的附加功能模块‌。以下是中间件的核心概念和特点:

‌一、中间件的本质

中间件本质上是 ‌"业务逻辑的增强层"‌,它像流水线上的加工环节,对输入的数据或事件进行预处理、拦截或后处理,但不改变核心逻辑本身。

‌二、典型特征‌

1、链式调用(洋葱模型)

多个中间件形成处理链,依次传递处理权,可以同时处理请求(Request)和响应(Response),类似流水线作业。

2、可插拔性

中间件可按需组合,灵活添加或移除功能模块,无需修改核心代码。

3、职责单一原则

每个中间件专注一个独立功能(如日志记录、权限验证等)。

‌三、核心工作原理

假设一个包含三个中间件的处理流程(伪代码):

// 中间件链式调用逻辑 const middlewareChain = [   (next) => (input) => {     console.log("Middleware 1开始");     next(input); // 传递到下一个中间件     console.log("Middleware 1结束");   },   (next) => (input) => {     console.log("Middleware 2开始");     next(input);     console.log("Middleware 2结束");   },   (next) => (input) => {     console.log("核心逻辑执行");     return "处理结果";   } ];  // 输出结果: // Middleware 1开始 // Middleware 2开始 // 核心逻辑执行 // Middleware 2结束 // Middleware 1结束

下面是一个手写redux的例子

createStore:

/**  * 判断是否是平面对象  * @param {*} obj   */ function isPlainObject(obj){     if(typeof obj!='object'){         return false;     }     return Object.getPrototypeOf(obj) === Object.prototype } /**  * 生成一个6位的随机字符串  */ function getRandomStr(len){     return Math.random().toString(36).substring(2,len+2).split("").join("."); } export default function(reducer,initState){     let currentReducer = reducer,currentState = initState;     let listens = [];     function dispatch(action){         //限制条件         //action 必须是一个平面对象         //必须有type属性         if(!isPlainObject(action)){             throw new TypeError('action必须是平面对象');         }         if(action.type === undefined){             throw new TypeError('action对象必须有type属性');         }         currentState = currentReducer(currentState,action);         //store更新完state之后 依次调用添加的监听器         for (const listen of listens) {             listen();         }     }     //初始化store的时候会默认 dispatch一个特殊的type类型     dispatch({         type:`@@redux/INIT${getRandomStr(6)}`     })      function getState(){         return currentState;     }      function subscribe(listen){         listens.push(listen);         //如果已经取消监听了 则直接返回         let isRemove = false;         //返回一个函数 执行清除监听器的操作         return function(){             if(isRemove){                 return;             }             const index = listens.indexOf(listen);             listens.splice(index,1);             isRemove = true;         }     }      return {         dispatch,         getState,         subscribe     } }

bindActionCreators:

/**  * //bindActionCreators 直接接收一个action创建函数 和 store.dispatch 如果是一个函数则直接调用 内部去dispatch action //如果接收的是一个对象 返回的跟对象属性相同的数据结构  内部去dispatch action  */ export default function(obj,dispatch){     if(typeof obj === "function"){         return getAutoDispatchAction(obj,dispatch)     }else if(typeof obj === "object"){         let result = {};         for (const key in obj) {             if (Object.prototype.hasOwnProperty.call(obj, key)) {                 const actionCreater = obj[key];                 result[key] = getAutoDispatchAction(actionCreater,dispatch);             }         }         return result;     }else{         throw new TypeError("报错了");     } }  function getAutoDispatchAction(actionCreate,dispatch){     /**      * 将参数汇总成数组  (arg1,arg2)  变成[arg1,arg2]      * 函数内部展开是重新变成(arg1,arg2) (展开运算符)      */     return function(...args){         const action = actionCreate(...args);         dispatch(action);     } }

applyMiddleware:

import compose from "./compose"; /**  * 外层函数捕捉中间件集合  * 中层函数接收创建原始厂库的函数  * 内层函数 用来增强原始厂库 增强原始的dispatch函数  */ export default function(...middlewares){     return function(createStore){         return function(reducer,defaultState){             const store = createStore(reducer,defaultState);             let dispatch = (...args)=>{                 throw new Error("Dispatching while constructing your middleware is not allowed. ");             };             const simpleStore = {                 getState:store.getState,                 dispatch:(...arge) => dispatch(...arge)             }             //返回的是创建dispatch函数的集合  每一个元素都是一个函数  调用函数会返回dispatch函数             const dispatchProducers = middlewares.map((mid)=>mid(simpleStore));             console.log(dispatchProducers)             dispatch = compose(...dispatchProducers)(store.dispatch)             return {                 ...store,                 dispatch             }         }     } }

compose:

export default function(...middlewares){     return middlewares.reduce((a,b)=>(...args)=>a(b(...args)))     // return function(...args){     //     let lastReturn = null;     //     for (let index = middlewares.length-1; index >=0; index--) {     //         //最后一个 将默认的dispatch传递给最后一个中间件  该中间件调用返回一个新的dispatch  并将这个新的dispatch作为参数传递给下一个中间件     //         if(index == middlewares.length-1){     //             //该函数接收一个dispatch函数 并返回一个新的dispatch函数     //             lastReturn = middlewares[index](...args)     //         }else{     //             lastReturn = middlewares[index](lastReturn);     //         }     //         lastReturn.displayName = `applayMiddle-${index}`;     //     }     //     return lastReturn;     // } }

中间件的组合逻辑:

其核心原理确实与闭包密切相关。具体执行流程如下:

  1. ‌中间件链式调用机制‌:
  • 代码通过倒序循环(从最后一个中间件开始)构建调用链
  • 每个中间件接收前一个中间件返回的函数作为参数(即next参数)
  • 最终返回的是包装了所有中间件逻辑的新dispatch函数
  1. ‌闭包的关键作用‌:
  • 每个中间件函数都通过闭包保存了对前一个中间件返回函数的引用
  • 当调用最终返回的dispatch时,会触发第一个中间件的执行,其内部的next()会调用闭包保存的下一个中间件
  • 这种链式调用会一直传递到原始dispatch(即代码中的...args

这种设计模式被称为"洋葱模型",请求从外层中间件进入,响应从内层中间件返回。闭包机制确保了每个中间件都能访问到正确的next函数引用,从而形成完整的调用链。

最后统一导出:

export {default as createStore} from './createStore'; export {default as bindActionCreators} from './bindActionCreators'; export {default as combineReducers} from './combineReducers'; export {default as applyMiddleware} from './applyMiddleware';

 

 

发表评论

评论已关闭。

相关文章