Redux中间件源码解析与实现

这篇具有很好参考价值的文章主要介绍了Redux中间件源码解析与实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基本介绍

本文中涉及到的关键npm包的版本信息如下:
react 的版本为18.2.0
redux的版本为4.1.2
redux-thunk版本为2.4.2
redux-promise版本为0.6.0
redux-logger版本为3.0.6

在Redux源码解析与实现(一)Redux源码解析与实现(二)这两篇文章中,详细讲解了怎么实现一个Redux的核心功能,而Redux默认只能够处理plainObject的参数,所以我们需要引用各种中间件来加强dispatch,使其能够传递异步函数或者是promise或者是其他的能力,比如说打日志。每个中间件往往也只做一件特定的事情,比如redux-thunk就是可以处理函数redux-logger可以打印出日志redux-promise可以处理actionpromise的情况。而且下一个中间件的接受的action为上一个中间件的处理的结果,如下图所示:

Redux中间件源码解析与实现,源码解析,中间件,redux中间件开发,redux中间件源码解析

基本使用

我们建一个简单的demo,看看redux-promise、redux-promise、redux-logger是如何使用的。我们只需要在createStore方法中传递经过applyMiddleware处理过的中间件即可,核心代码如下:

// store/index.js
import thunk from 'redux-thunk'
import logger from 'redux-logger'
import promise from 'redux-promise'

const store = createStore(
  rootReducer,
  // logger 要在thunk的后面,dispatch接受的参数可能是函数经过thunk处理之后再return一个planObject再交给logger处理
  applyMiddleware(promise, thunk, logger)
)

// ReduxPage.jsx
import React from "react";
import store from "../store";
import './index.css'

export default class ReduxPage extends React.Component {

  componentDidMount() {
    // 新增订阅,在这里订阅的逻辑就是当状态管理库store中数据更新时,组件也需要更新一下
    this.unsubscribe = store.subscribe(() => {
      this.forceUpdate()
    })
  }

  componentWillUnmount() {
    // 组件卸载 -> 自然需要取消订阅
    this.unsubscribe()
  }

  add = () => {
    store.dispatch({type: "ADD"})
  }

  asyncAdd = () => {
    store.dispatch((dispatch, getState) => {
      console.log('getState pre:', getState());
      // 使用setTineout模拟后端请求
      setTimeout(() => {
        // 拿到服务端数据,处理完数据之后再dispatch
        dispatch({type: "ADD", payload: 10})
        console.log('getState after:', getState());
      }, 1000)
    })
  }

  promiseAdd = () => {
    // dispatch接受一个promise的参数
    // store.dispatch(Promise.resolve({type: 'ADD', payload: 20}))
    store.dispatch(new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({type: 'ADD', payload: 20})
      }, 1000)
    }))

  }

  minus = () => {
    store.dispatch({type: "MINUS"})
  }

  setName = () => {
    store.dispatch({type: "SET_NAME", payload: `hyy${Math.random()}`})
  }
  
  setAge = () => {
    store.dispatch({type: "SET_AGE", payload: Math.random() * 100})
  }

  render() {
    return (
      <div>
        <div> ReduxPage </div>
        <div>
          <span className="box">count: {store.getState().count}</span>
          <span className="box">name: {store.getState().userInfo.name}</span>
          <span className="box">age: {store.getState().userInfo.age}</span>
        </div>
        <div className="wrap">
          <button onClick={this.add}>add</button>
          <button onClick={this.asyncAdd}>asyncAdd</button>
          <button onClick={this.promiseAdd}>promiseAdd</button>
          <button onClick={this.minus}>minus</button>
        </div>
        <div className="wrap">
          <button onClick={this.setName}>setName</button>
          <button onClick={this.setAge}>setAge</button>
        </div>
      </div>
    );
  }
}

经过Redux源码解析与实现(一)Redux源码解析与实现(二)我们知道在用户在dispatch的时候会依次执行各个中间件,而中间件会接受到dispatch & getStore这个对象以读写store中的数据然后返回值给下一个中间件执行。直至最后应该得到一个plainObject传递给原始的dispatch执行。其中通过applyMiddleware接受到的若干个中间件函数数组则是使用了函数式编程思想中函数聚合的方式依次执行。

redux中间件的基本使用demo

源码分析

经过上面的分析,所有的中间件的代码架子均如下所示:

function xxx({getState, dispatch}) {
	// next就是聚合函数componse中的下一个要执行的函数(reducer中的func)
  return (next) => (action) => {
  	// todo...
  	// returnValue就是该中间件处理完之后返回给下一个中间件的值
    return returnValue;
  };
}

代码实现

redux-promise

这个中间件主要是判断当前传递的参数即action是否是promise,如果是的话,那我们就需要通过promise的方式获取值然后返回给下一个中间件,如果不是的话,那就直接运行当前函数即可。其代码基本实现如下:

function promise({getState, dispatch}) {
  return (next) => (action) => {
  	// 判断传递进来的action是否为promise
    return isPromise(action) ? action.then(dispatch) : next(action);
  };
}

redux-thunk

这个中间件主要是判断当前的action是否是函数,如果是函数的话,那就执行该函数并将dispatch & getStore两个操作状态管理库的API传递给这个函数,这个函数执行的结果return给下一个中间件的入参,如果不是一个函数,那就将action传递给当前函数执行&返回结果给下一个中间件其主要核心代码如下:

// 自定义thunk中间件
// 中间件接受的参数就是middlewareAPI即getState & dispatch 让中间件有操作状态管理库的权限
function thunk({getState, dispatch}) {
  // ! next就是聚合函数componse中的下一个要执行的函数(reducer中的func)而不是下一个中间件
  return (next) => (action) => {
    if (typeof action === "function") {
      // 如果接受到一个函数的话就执行这个函数 & 把dispatch和getState作为参数传递给这个函数
      // 所以业务代码传递给dispatch的函数参数可以接受dispatch, getState这两个参数
      return action(dispatch, getState);
    }
    // 如果action不是函数那就正常执行 并把当前函数执行的值return给下一个中间件
    return next(action);
  };
}

redux-logger

这个中间件主要是在dispatch的时候打印出了一些日志,便于我们做数据追踪,我们可以在数据修改之前(即dispatch之前打印出原始数据 )+ action动作和数据被修改之后(即dispatch之后的store中的数据)
其核心代码如下:

// 自定义logger 中间件
function logger({getState, dispatch}) {
  return (next) => (action) => {
    console.log("------------------------------------------");
    console.log("prev state", getState());

    console.log(`${action.type ? `ACTION: ${action.type + "已被执行~"}` : '接受到action为非plainObject'}`);

    const returnValue = next(action);

    console.log("next state", getState());

    console.log("------------------------------------------");

    return returnValue;
  };
}

我们将示例中的中间件部分换成我们自己开发的中间件查看下效果:
Redux中间件源码解析与实现,源码解析,中间件,redux中间件开发,redux中间件源码解析

线上demo: redux中间件的基本实现

相关资料

redux
redux-thunk
redux-logger
redux-promise
Redux源码解析与实现(一)
Redux源码解析与实现(二)
redux中间件的基本使用demo
redux中间件的基本实现文章来源地址https://www.toymoban.com/news/detail-709300.html

到了这里,关于Redux中间件源码解析与实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【.NET源码解读】深入剖析中间件的设计与实现

    .NET本身就是一个基于中间件(middleware)的框架,它通过一系列的中间件组件来处理HTTP请求和响应。在之前的文章《.NET源码解读kestrel服务器及创建HttpContext对象流程》中,已经通过源码介绍了如何将HTTP数据包转换为.NET的HttpContext对象。接下来,让我们深入了解一下.NET是如何

    2024年02月11日
    浏览(28)
  • Go重写Redis中间件 - Go实现Redis协议解析器

    Redis网络协议详解 在解决完通信后,下一步就是搞清楚 Redis 的协议-RESP协议,其实就是一套类似JSON、Protocol Buffers的序列化协议,也就是我们的客户端和服务端通信的协议 RESP定义了5种格式 简单字符串(Simple String) : 服务器用来返回简单的结果,以\\\"+\\\"开头,\\\"rn\\\"结尾的字符串形

    2024年02月15日
    浏览(39)
  • 探索Scrapy中间件:自定义Selenium中间件实例解析

    Scrapy是一个强大的Python爬虫框架,可用于从网站上抓取数据。本教程将指导你创建自己的Scrapy爬虫。其中,中间件是其重要特性之一,允许开发者在爬取过程中拦截和处理请求与响应,实现个性化的爬虫行为。 本篇博客将深入探讨Scrapy中间件的关键作用,并以一个实例详细介

    2024年02月04日
    浏览(53)
  • 中间件漏洞解析

     服务器解析漏洞算是历史比较悠久了,但如今依然广泛存在。在此记录汇总一些常见服务器(WEB server)的解析漏洞,比如IIS6.0、IIS7.5、apache、nginx等 2 | 1 1、打开之前的一个网站,比如:cookies 2 | 2 2.目录解析漏洞 找到cookies,新建一个名字为.asp(也可以是.cer和.asa)的文件夹,这

    2024年02月12日
    浏览(37)
  • 20230529----重返学习-复合组件通信redux-redux源码-redux工程化开发-自定义hook

    要想实现复合组件通信,一般采用公共状态管理方案。 常见的公共状态管理方案: 官方推荐的:redux。 redux + react-redux + redux-logger / redux-promise / redux-saga / redux-thunk :中间件。 代表:dva「redux-saga 」或 umi。 @reduxjs/toolkit :工具类。 mobx 。 zustand 。 … redux的应用场景 redux 在以

    2024年02月06日
    浏览(37)
  • 中间件安全IIS----文件解析漏洞利用

          IIS服务器主要存在两种解析缺陷:文件夹解析漏洞和分号截断漏洞。下面就来分别具体 了解一下。        在IS5x和6.0下对于录名称为“xasp”中的任何内容,包括“1.jpg”这样的图片文件,都会被当作ASP文件解析。例如“/example.asp/1.jpg”,这本来是一个图片资源,但是

    2024年01月18日
    浏览(36)
  • 消息中间件之RocketMQ源码分析(十)

    启动命令 nohup ./bin/mqnamesrv -c ./conf/namesrv.conf dev/null 21 通过脚本配置启动基本参数,比如配置文件路径、JVM参数,调用NamesrvStartup.main()方法,解析命令行的参数,将处理好的参数转化为Java实例,传递给NamesrvController实例 加载命令行传递的配置参数,调用controller.initialize()方法初

    2024年02月20日
    浏览(42)
  • 六、用 ChatGPT 学习 Eureka 中间件源码

    目录 一、实验介绍 二、背景 三、ChatGPT 帮助分析 Eureka 源码 3.1 Eureka 源码在哪

    2024年02月16日
    浏览(31)
  • day33 文件上传&中间件解析漏洞&编辑器安全

    先判断中间件,是否有解析漏洞,字典扫描拿到上传点,或者会员中心,有可能存在文件上传的地方,而后测试绕过/验证,根据实际情况判断是白名单、黑名单还是内容其他的绕过,绕过/验证和中间件的解析漏洞也不行的话就看看CMS是否存在漏洞,然后看看编辑器漏洞有无

    2024年02月05日
    浏览(33)
  • 【开发】中间件——ElasticSearch

    ElasticSearch是一个基于Lucene的搜索服务器。提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口 ElasticSearch是一个基于Lucene的搜索服务器。提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口 ElasticSearch是用JAVA开发的。达到实时搜索,稳定可靠,快速,

    2024年02月17日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包