零、随便说说中间件

  在react的使用中,我们可以将数据放到redux,甚至将一些数据相关的业务逻辑放到redux,这样可以简化我们组件,也更方便组件抽离、封装、复用,只是redux不能很好的处理异步,当我们获取接口数据的时候,redux就满足不了我们的需要。然后,中间件就出来了,使用中间件可以满足我们异步获取数据,当然也可以干其他的事;

  我们都知道一个数据更新,经过component >> action  >> dispatch >> reducers >> state >> store >> component,这样一个过程。其实,中间件的本质就是 把异步的这种情况单独的拿出来处理,然后还是把数据经过redux处理了。也就是说做中间件的关键是先把正常的action 和 异步的action 区分出来,从上边的流程看也只能是action >> dispatch 这一步了。

  下边看看中间件相关的一些源码,从createStore开始:

一、createStore

const createStore = (reducers, initialState, enhancer) => {
  if (typeof initialState === 'function' && typeof enhancer === 'undefined') {
    enhancer = initalState;
  initialState = undefined;
}
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
//校验enhancer是否为函数,如果不是函数则抛出异常
throw new Error('Expected the enhancer to be a function.')
}
//如果enhancer存在且为函数,那么则返回如下调用,如果enhancer为applyMiddleware,那么调用则
//是applyMiddleware(createStore)(reducer, preloadedState)。后面讲applyMiddleware再详细讲。
return enhancer(createStore)(reducer, preloadedState)
}
  ....
  // 下边就是没有中间件的时候,返回一些state的方法如:getState, dispatch...
}

  这就是做了个区分,有中间件和没中间件的区分,有中间件返回的是中间件代码:enhancer(createStore)(reducer, preloadedState),没有就直接返回一些方法;

二、applyMiddleware

const applyMiddleware = (...middlewares) => (createStore) => (reducer, initial, enhancer) => {
const store = createStore(reducer, initial, enhancer);
let dispatch = store.dispatch;
let chain = [];
const middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}; chain = middlewares.map(middleware => middleware(middlewareAPI));// a
dispatch = compose(...chain)(store.dispatch); // b return { ...store, dispatch };
}

  看名字就可以知道这是应用中间件的一个方法,他是将中间件 middlewares 和 store 结合返回一个新的store对象,实际上是对 dispatch 的重写;

  结合上边的 createStore 源码我们可以看到,当有中间件的时候 createStore 返回的实际上就是 applyMiddleware 的一个执行结果,从参数看是从第二层的方法开始的,那是因为,我们在执行 createStore之前,会有下面的一步操作:

const enhancer = applyMiddleware(...middlewares)
const store = createStore(reducer, enhancer)

  其实可以看到在 applyMiddleware 中利用 createState 重新生成了 store,并对 dispatch 进行了重写:先将每一个中间件都执行一次,参数是 middlewareAPI ,然后将返回的数组, 借助于 compose,以原生 dispatch 为参数执行,返回新的 dispatch,最后替换 store 里的 dispatch 并作为新的 store 返回;这个返回结果实际上就是 createStore 中,有中间件传入时的返回结果。

  可能会对 dispatch 重写的过程会不太清楚,下边看看 compose 源码:

三、compose

const compose = (...middlewares) => {
if (middlewares.length === 0) {
return arg => arg;
} else {
const last = middlewares[middlewares.length - 1];
const reset = middlewares.slice(0, -1);
return (args) => rest.reduceRight((composed, f) => f(composed), last(args))
}
}

  结合着 applyMiddleware 看这个源码会更好没理解一点。(reducerRight 方法不熟的朋友,百度一下)

  当传入中间件数组的时候,返回的是一个带参数的方法, 参数就是相当于上面的 dispatch ,取出最后一个中间件执行,并最为 reducerRight 的 初始值,执行reducerRight 方法;

四、中间件的方法 middleware

const middleware = ({ state, dispatch}) => (next) => (action) => {
if (typeof action === 'funtion') {
return net(action);
}
dispatch(action);
}

  中间件的本质:判断你要处理的情况,执行你想要执行的方法,如果是异步,我们 action 通常是方法,所以就执行next,如果不是异步执行的就是原生 dispatch;

  中间件的第一层是在 applyMiddleware 中执行的(标注a处),第二层是 applyMiddleware 中 compose 中执行的(标注b处),其实 next 就是原生的 dispatch 或者已经重写的 dispatch (即 middleware 中最后一层的方法);

五、没有了

  到目前为止这个中间件相关的源码算是搞完了,理解这些感觉写个中间件基本上没问题,推荐看看 redux-thunk 源码其实很简单,和第四步的差不多;

  

  有一个中间件的小Dome:https://github.com/wayaha/react-demos-middleware

  敢不敢点个星!!!

react 中间件相关的一些源码解析的更多相关文章

  1. TongWEB与JOnAS 对比,国产中间件战斗机东方通TongWEB源码解析

    转自网址: http://bbs.51cto.com/thread-489819-1-1.html 首先需要声明的是,本人出于技术爱好的角度,以下的文字只是对所看到的一些情况的罗列,偶尔附加个人的一些 ...

  2. laravel源码解析

    本专栏系列文章已经收录到 GitBooklaravel源码解析 Laravel Passport——OAuth2 API 认证系统源码解析(下)laravel源码解析 Laravel Passport ...

  3. AspNetCore3.1_Middleware源码解析_3_HttpsRedirection

    概述 上文提到3.1版本默认没有使用Hsts,但是使用了这个中间件.看名字就很好理解,https跳转,顾名思义,就是跳转到 https地址. 使用场景,当用户使用http访问网站时,自动跳转到http ...

  4. AspNetCore源码解析_1_CORS中间件

    概述 什么是跨域 在前后端分离开发方式中,跨域是我们经常会遇到的问题.所谓的跨域,就是处于安全考虑,A域名向B域名发出Ajax请求,浏览器会拒绝,抛出类似下图的错误. JSONP JSONP不是标准跨 ...

  5. .Net Core 中间件之主机地址过滤(HostFiltering)源码解析

    一.介绍 主机地址过滤中间件相当于一个白名单,标记哪些主机地址能访问接口. 二.使用 新建WebAPI项目,修改Startup中的代码段如下所示.下面表示允许主机名为“localhost”的主机访问( ...

  6. React源码解析之React.Children.map()(五)

    一,React.Children是什么? 是为了处理this.props.children(this.props.children表示所有组件的子节点)这个属性提供的工具,是顶层的api之一 二,Re ...

  7. React的React.createContext()源码解析(四)

    一.产生context原因 从父组件直接传值到孙子组件,而不必一层一层的通过props进行传值,相比较以前的那种传值更加的方便.简介. 二.context的两种实现方式 1.老版本(React16.x ...

  8. React的React.createRef()/forwardRef()源码解析(三)

    1.refs三种使用用法 1.字符串 1.1 dom节点上使用 获取真实的dom节点 //使用步骤: 1. <input ref="stringRef" /> 2. t ...

  9. React的Component,PureComponent源码解析(二)

    1.什么是Component,PureComponent? 都是class方式定义的基类,两者没有什么大的区别,只是PureComponent内部使用shouldComponentUpdate(nex ...

随机推荐

  1. javascript系列-class9.DOM(上)

    欢迎加入前端交流群交流知识获取视频资料:749539640 1.文档对象模型DOM(document Object Model)        所谓DOM就是以家族的形式描述HTML       节点 ...

  2. Linux下处理JSON的命令行工具:jq---安装

    转自:https://blog.csdn.net/Sunny_much/article/details/50668871      JSON是前端编程经常用到的格式.Linux下也有处理处理JSON的 ...

  3. asp.net 汉字转拼音的车祸现场

    asp.net 汉字转拼音 需求背景: 昨天遇到个问题,就是面对系统中集中性的要设置大批量的用户设置默认的用户名,密码,权限(角色),同时要求用户名是姓名的全拼,回头看看旁边那个哥们撸胳膊挽袖子准备一 ...

  4. ES6 | 关于class类 继承总结

    子类必须在constructor方法中调用super方法,否则新建实例时会报错.这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工.如果不调用super方法,子类就得不到 ...

  5. 你不知道的JavaScript(十)with关键字

    with关键字在JavaScript中不太常用,用来定义一个和对象相关的作用域,在该作用域中可以访问对象的属性或方法而前面无需加上对象名,以达到简化代码的目的. <script type=&qu ...

  6. javascript工具--控制台详解

    一.显示信息的命令 console.log();  //控制台输入 网页中不会输出 console.info();  //一般信息 console.debug();  //除错信息 console.w ...

  7. C++12.1.4 类的前向声明、不完全类型类

    只声明却没有定义的类称为—————–不完全类型,不完全类型不能定义该类型的对象,只能用于定义指向该类型的指针及引用,或者用于声明(不是定义)使用该类型作为形参类型或返回类型的函数. 在创建类的对象之前 ...

  8. Dbf文件操作

    package cn.com.szhtkj.util; import java.io.File; import java.io.IOException; import java.lang.reflec ...

  9. checkbox控制显示隐藏

    显示文本框<input type = "checkbox" id="checkbox" onclick="on_hide();"/&g ...

  10. 路飞学城Python-Day17

    [1.编程范式] 1.面向过程编程 2.面向对象编程 [2.面向过程编程] 面向过程:核心就是过程   什么是过程? 过程指的是解决问题的步骤,先做什么,在作什么,面向过程就像是设计一个流水线,是一种 ...