齐娅晶 发表于 2025-6-2 23:43:01

详解中间件

中间件(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;
                result = getAutoDispatchAction(actionCreater,dispatch);
            }
      }
      return result;
    }else{
      throw new TypeError("报错了");
    }
}

function getAutoDispatchAction(actionCreate,dispatch){
    /**
   * 将参数汇总成数组(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(...args)
    //         }else{
    //             lastReturn = middlewares(lastReturn);
    //         }
    //         lastReturn.displayName = `applayMiddle-${index}`;
    //   }
    //   return lastReturn;
    // }
}中间件的组合逻辑:
其核心原理确实与闭包密切相关。具体执行流程如下:

[*]‌中间件链式调用机制‌:


[*]代码通过倒序循环(从最后一个中间件开始)构建调用链
[*]每个中间件接收前一个中间件返回的函数作为参数(即next参数)
[*]最终返回的是包装了所有中间件逻辑的新dispatch函数

[*]‌闭包的关键作用‌:


[*]每个中间件函数都通过闭包保存了对前一个中间件返回函数的引用
[*]当调用最终返回的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'; 
 
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 详解中间件