写点什么

详解中间件

  • 2025-05-16
    福建
  • 本文字数:3358 字

    阅读完需:约 11 分钟

中间件(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 函数


2‌、闭包的关键作用‌:

  • 每个中间件函数都通过闭包保存了对前一个中间件返回函数的引用

  • 当调用最终返回的 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';
复制代码


文章转载自:飞奔的龟龟

原文链接:https://www.cnblogs.com/nianzhilian/p/18877335

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

还未添加个人签名 2025-04-01 加入

还未添加个人简介

评论

发布
暂无评论
详解中间件_中间件_量贩潮汐·WholesaleTide_InfoQ写作社区