redux 中间件 --- applyMiddleware 源码解析 + 中间件的实战

简介: 前传  中间件的由来  redux的操作的过程,用户操作的时候,我们通过dispatch分发一个action,纯函数reducer检测到该操作,并根据action的type属性,进行相应的运算,返回state,然后更新view。

前传  中间件的由来

  redux的操作的过程,用户操作的时候,我们通过dispatch分发一个action,纯函数reducer检测到该操作,并根据action的type属性,进行相应的运算,返回state,然后更新view。

  但是一个很重要的问题,reducer对于action会立即进行运算,并返回state,如果我们的操作是要获取服务端的数据,需要调用接口类似的异步操作呢?很明显这样操作不行。所以,middleware中间件诞生了,中间件就是处理reducer处理不了的问题,对reducer做一个补充,配合。

  我们就以使用中间件来解决异步问题为例来说,中间件顾名思义,就是作为一个流程的一个中间处理程序存在,它是放到一个流程的中的。问题是在处理一部问题,我们把他放哪的问题

    a、action只是一个跑腿的,把操作的相关数据带到reducer;

    b、reducer只是个干活的,纯函数,计算一下嘛,返回新的数据,异步操作它搞不了;

    c、view,理论上这或者是显示的,不会有太多的逻辑,中间件肯定不能放;

    d、剩下的就是把action分发到reducer的dispatch了,我们可以在分发的时候做点手脚。

 

看看applyMiddleware

  中间件知道放在哪了,我们看看实现中间件的重要api ----- applyMiddleware 的源码

 

function applyMiddleware() {
  for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) {
    middlewares[_key] = arguments[_key];
  }

  return function (createStore) { // 以下称这个方法为func1
    return function () { // 以下称这个方法为func2
      for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
        args[_key2] = arguments[_key2];
      }

      var store = createStore.apply(undefined, args);// 调用createStore方法生成store
    // 初始化一个新的dispatch,暂时认为_dispatch = store.dispatch,从效果上看是这样的,暂时不明白为什么这样写,有待大牛指点。
var _dispatch = function dispatch() { throw new Error('Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.'); }; var middlewareAPI = { getState: store.getState, dispatch: function dispatch() { return _dispatch.apply(undefined, arguments); } };
    //让每一个中间件调用一次,参数为middlewareAPI,并把结果方法chain中,注意这个地方,是中间件的第一层,参数是{getState, dispatch}
var chain = middlewares.map(function (middleware) { return middleware(middlewareAPI); });
    // 将各个中间件的功能组合到 dispatch 上,生成新的dispatch,注意此时是中间件的第二层, 参数是store.dispatch (关于 compose 解析) _dispatch
= compose.apply(undefined, chain)(store.dispatch);
      return _extends({},
        store, // 最终返回的是store数据和加强后的dispatch         {dispatch: _dispatch} ); }; }; }

 

  a、applyMiddleware 方法本身

    它首先通过一个for循环,将它的形参以数组元素的形式放到 middleware 中,并返回了一个形参为 createStore 方法(即为标注的func1);

  b、形参为 createStore 方法(即为标注的func1)

    这货很懒,只是返回了一个有很多参数的方法(即为标注的func2);

  c、很多参数的方法(即为标注的func2)

    这个方法和 applyMiddleware 一样,它首先通过一个for循环,将它的形参以数组元素的形式放到 args中;

  具体源码的解析,请看源码的注释;

中间件的编写

  我在源码的解析中,写了两个注意,分别是中间件的第一层和第二层,多以中间件的外面两层应该是如下的:

const timeOutMiddleware = ({ dispatch, getState }) => {
    return (storeDispatch) => {
        return { ... };
    };
}

  根据 compose 的操作原理,每一个中间件,即 chain 中的每一个元素,参数都是前一个中间件的组合后的 dispatch,返回的都是在参数的基础上组合自己功能后的dispatch,chain最后一个元素参数是store.dispatch。因此return的应该是一个通过这些中间件加强后的 dispatch。在此,我们就可以根据action传入的数据进行区分,加入我们中间件具体需要处理的情况。如下:

const timeOutMiddleware  = ({ dispatch, getState }) => (storeDispatch) => (action) => {
    if (typeof action === 'function') {
        return action(dispatch, getState);
    } else {
        return storeDispatch(action);
    }
};

  如上,我们如果传入正常的action,我们就执行正常的store.dispatch。如果我们 action 传入的是 function 类型,那么这就是我们中间件处理的情况了。在action的function中我们可以拿到 store 的 dispatch 和 store 的 getState。当然我们在这个方法中可以异步的获取服务端的数据,然后根据成功或者失败的结果,通过 dispatch 再次分发一个正常的 action 同步我们获取到的数据,执行相应的操作。如下

deleteStaff = (data) => {
        const { dispatch } = this.props;
        const { staffId } = data;
        const action = (dispatchd, getState) => {
            setTimeout(() => {
                dispatchd({type: 'DELETE', payload: {staffId}});
            }, 3000);
        };
        dispatch(action);
        };

 这是一个方法,删除一条数据,通过 setTimeout 模仿异步,在3秒后,再次发一个 action,执行删除数据;

本文栗子的代码:https://github.com/wayaha/react-demos-middleware

(对您有帮助的话,请您帮我点颗 star)

 

目录
相关文章
|
JavaScript 中间件 开发者
Redux 中间件和 MobX 的响应式机制有何区别?
Redux 中间件和 MobX 的响应式机制有何区别?
484 75
|
数据采集 自然语言处理 NoSQL
利用中间件实现任务去重与分发精细化:股吧舆情数据采集与分析实战
本项目针对东方财富股吧设计精细化采集方案,解决重复采集、调度混乱与反爬等问题,构建舆情分析数据模型。通过采集帖子内容、用户行为与情绪信号,实现情绪趋势可视化、热点识别与个股预警,助力把握市场风向。
886 0
利用中间件实现任务去重与分发精细化:股吧舆情数据采集与分析实战
|
JSON 中间件 Java
【GoGin】(3)Gin的数据渲染和中间件的使用:数据渲染、返回JSON、浅.JSON()源码、中间件、Next()方法
我们在正常注册中间件时,会打断原有的运行流程,但是你可以在中间件函数内部添加Next()方法,这样可以让原有的运行流程继续执行,当原有的运行流程结束后再回来执行中间件内部的内容。​ c.Writer.WriteHeaderNow()还会写入文本流中。可以看到使用next后,正常执行流程中并没有获得到中间件设置的值。接口还提供了一个可以修改ContentType的方法。判断了传入的状态码是否符合正确的状态码,并返回。在内部封装时,只是标注了不同的render类型。再看一下其他返回的类型;
582 3
|
缓存 监控 中间件
Django中间件自定义开发指南:从原理到实战的深度解析
Django中间件是Web应用的“交通警察”,在请求与响应过程中进行全局处理,适用于身份验证、日志记录、性能监控等功能。本文详解中间件的工作原理、开发步骤及实战案例,帮助开发者掌握自定义中间件的构建方法,提升Django应用的可维护性与扩展性。
684 0
|
人工智能 API 开发者
HarmonyOS Next~鸿蒙应用框架开发实战:Ability Kit与Accessibility Kit深度解析
本书深入解析HarmonyOS应用框架开发,聚焦Ability Kit与Accessibility Kit两大核心组件。Ability Kit通过FA/PA双引擎架构实现跨设备协同,支持分布式能力开发;Accessibility Kit提供无障碍服务构建方案,优化用户体验。内容涵盖设计理念、实践案例、调试优化及未来演进方向,助力开发者打造高效、包容的分布式应用,体现HarmonyOS生态价值。
1194 27
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
1782 29
|
数据采集 JSON 数据可视化
JSON数据解析实战:从嵌套结构到结构化表格
在信息爆炸的时代,从杂乱数据中提取精准知识图谱是数据侦探的挑战。本文以Google Scholar为例,解析嵌套JSON数据,提取文献信息并转换为结构化表格,通过Graphviz制作技术关系图谱,揭示文献间的隐秘联系。代码涵盖代理IP、请求头设置、JSON解析及可视化,提供完整实战案例。
1045 4
JSON数据解析实战:从嵌套结构到结构化表格
|
数据采集 机器学习/深度学习 存储
可穿戴设备如何重塑医疗健康:技术解析与应用实战
可穿戴设备如何重塑医疗健康:技术解析与应用实战
1022 4
|
机器学习/深度学习 人工智能 Java
Java机器学习实战:基于DJL框架的手写数字识别全解析
在人工智能蓬勃发展的今天,Python凭借丰富的生态库(如TensorFlow、PyTorch)成为AI开发的首选语言。但Java作为企业级应用的基石,其在生产环境部署、性能优化和工程化方面的优势不容忽视。DJL(Deep Java Library)的出现完美填补了Java在深度学习领域的空白,它提供了一套统一的API,允许开发者无缝对接主流深度学习框架,将AI模型高效部署到Java生态中。本文将通过手写数字识别的完整流程,深入解析DJL框架的核心机制与应用实践。
1140 3
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
789 4

推荐镜像

更多
  • DNS