react 中间件相关的一些源码解析

零、随便说说中间件

  在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 = compose(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

  敢不敢点个星!!!

原文地址:https://www.cnblogs.com/this-day/p/10338996.html

时间: 2024-08-10 13:31:05

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

spring-beans中Aware相关接口的源码解析说明

spring版本为5.0.11 Aware是个没有定义任何方法的接口,即标记超接口,拥有众多子接口,在spring源码中有多处都在使用这些子接口完成各种场景下的回调操作. aware字面意思翻译过来是知道的,感知的,所以理解为感知所有aware前面的含义. beanNameAware接口(不建议使用):如果某个bean需要访问配置文件中本身bean的id属性,这个Bean类通过实现该接口,在依赖关系确定之后,初始化方法之前,提供回调自身的能力,从而获得本身bean的id属性,该接口提供了void

fork()相关的源码解析

fork()的真正执行采用的是do_fork()函数,所以下文将从do_fork()函数对fork()进行源码解析.下图是do_fork()的源码函数设计: 从上图我们可以看到do_fork()涉及到众多的参数.所以在进入do_fork函数进行分析之前,很有必要了解一下它的参数. clone_flags:克隆标识: * * cloning flags: */#define CSIGNAL 0x000000ff /* signal mask to be sent at exit *//** * 共

Redux系列x:源码解析

写在前面 redux的源码很简洁,除了applyMiddleware比较绕难以理解外,大部分还是 这里假设读者对redux有一定了解,就不科普redux的概念和API啥的啦,这部分建议直接看官方文档. 此外,源码解析的中文批注版已上传至github,可点击查看.本文相关示例代码,可点击查看. 源码解析概览 将redux下载下来,然后看下他的目录结构. npm install redux 这里我们需要关心的主要是src目录,源码解析需要关心的文件都在这里面了 index.js:redux主文件,主

Spring IoC源码解析——Bean的创建和初始化

Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,MyBatis框架等组合使用. IoC介绍 IoC是什么 Ioc-Inversion of Control,即"控制反转",不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控

RN FlatList使用详解及源码解析

FlatList使用详解及源码解析 前言 长列表或者无限下拉列表是最常见的应用场景之一.RN 提供的 ListView 组件,在长列表这种数据量大的场景下,性能堪忧.而在最新的 0.43 版本中,提供了 FlatList 组件,或许就是你需要的高性能长列表解决方案.它足以应对大多数的长列表场景. 一.功能简介 FlatList高性能的简单列表组件,支持下面这些常用的功能: 完全跨平台. 支持水平布局模式. 行组件显示或隐藏时可配置回调事件. 支持单独的头部组件. 支持单独的尾部组件. 支持自定义

《Druid源码解析(1) Guice和Realtime流程》——图较精简,不错

https://zqhxuyuan.github.io/ 最近两年更新少 任何忧伤,都抵不过世界的美丽 2015-12-08 Druid源码解析(1) Guice和Realtime流程 Source druid Druid is a fast column-oriented distributed data store. http://druid.io/ 当启动Druid的服务,会启动一个java进程,比如run_example_server.sh会启动io.druid.cli.Main exa

Axios使用及源码解析

Axios使用及源码解析 简介 axios 是一个用于浏览器和Node.js上的基于 Promise 的http网络库. 大纲 使用方式 安装: npm install axios 使用: //引入axios const axios = require('axios'); import axios from 'axios'; axios的四种使用方式 1. axios(config) 直接将相关配置包括请求url作为参数传入到axios方法中 axios({ url: 'https://json

String源码解析(一)

本篇文章内的方法介绍,在方法的上面的注释讲解的很清楚,这里只阐述一些要点. Java中的String类的定义如下: 1 public final class String 2 implements java.io.Serializable, Comparable<String>, CharSequence { ...} 可以看到,String是final的,而且继承了Serializable.Comparable和CharSequence接口. 正是因为这个特性,字符串对象可以被共享,例如下面

Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例

概要 上一章,我们学习了Collection的架构.这一章开始,我们对Collection的具体实现类进行讲解:首先,讲解List,而List中ArrayList又最为常用.因此,本章我们讲解ArrayList.先对ArrayList有个整体认识,再学习它的源码,最后再通过例子来学习如何使用它.内容包括:第1部分 ArrayList简介第2部分 ArrayList数据结构第3部分 ArrayList源码解析(基于JDK1.6.0_45)第4部分 ArrayList遍历方式第5部分 toArray