Redux快速上手之【redux中间件及处理机制】

前言

  • 细阅此文章大概需要 <math xmlns="http://www.w3.org/1998/Math/MathML"> 7 分钟 \color{red}{7分钟} </math>7分钟左右

  • 本篇中讲述了:

    1. 什么是中间件
    2. 常见的中间件
    3. 中间件的使用
    4. 异步派发为什么要使用中间件
    5. redux-thunk中间件的使用及原理
    6. redux-promise中间件的使用及原理
    7. redux-thunkredux-promise的异同
  • 欢迎在评论区探讨、留言,如果认为有任何错误都还请您不吝赐教,万分感谢。希望今后能和大家共同学习、进步。

  • 下一篇会尽快更新,已经写好的文章也会在今后进行不定期的修订、更新。

  • 如果觉得这篇文章对您有帮助,还请点个赞支持一下,谢谢大家!

  • 欢迎转载,注明出处即可。


什么是中间件

当我们在执行dispatch派发时,如果使用了中间件,那么派发前就会先经过中间件去执行一系列操作,然后再进行派发。


常见的中间件

redux-logger

此中间件提供了日志能力,当我们每次进行派发的时候,它可以在控制台输出日志。日志内容包括:派发前的状态派发的行为派发后的状态

redux-thunk/redux-promise

这两种中间件提供了异步派发的能力。每次派发的时候,需要传递给reduceraction对象中的内容是需要异步进行获取的。

redux-saga


中间件的使用

redux中使用中间件,需要配合applyMiddleware这个api来使用。applyMiddleware方法可以接收多个中间件实例/方法作为参数。

js 复制代码
// 创建公共容器
import {createStore, applyMiddleware} from 'redux'
import reducer from './reducer'
import reduxLogger from 'redux-logger' // 引入logger中间件

/*创建公共容器*/
const store = createStore(
    reducer,
    applyMiddleware(reduxLogger) //在创建公共容器时,通过applyMiddleware来注入并使用中间件,这里可以传入多个中间件
)

export defualt store

异步派发为什么要使用中间件

当不使用任何中间件的情况下,在actionCreator对象中,是不支持异步操作的。因为如果我们自己通过promise来实现异步派发,action得到的是一个promise实例,并不是一个标准的action对象,且不存在type属性。要保证方法的执行,必须立即返回标准的action对象

而在应用的redux的项目中,往往很多时候,都需要用到异步派发:比如我们派发后,需要先请求数据,等到数据回来,在进行派发操作。

这种场景下,官方最为推荐的就是使用redux-thunk中间件。

js 复制代码
// 创建公共容器
import {createStore, applyMiddleware} from 'redux'
import reducer from './reducer'
import reduxLogger from 'redux-logger'
import reduxThunk from 'redux-thunk' // 引入thunk中间件

/*创建公共容器*/
const store = createStore(
    reducer,
    applyMiddleware(reduxLogger, reduxThunk) //在创建公共容器时,通过applyMiddleware来注入并使用中间件,这里可以传入多个中间件
)

export defualt store

thunk中间件的使用及原理

使用

在使用上和logger差不多,都需要通过applyMiddleware来注入。 唯一不同的地方在于:actionCreator在编写时候的结构有所调整,要求我们先返回一个函数,然后在这个函数中进行异步操作,等到异步操作完成,在手动进行dispatch派发

原理

  1. 当我们触发交互,执行adda方法,会将moduleAAction.adda()执行,执行的返回值进行派发

第一次派发:派发的其实是一个函数,这次派发用到的dispatch其实是重写的这个dispatch,传递给dispatch的其实是一个函数【无type】,此时不会报错,也不会通知reducer执行,仅仅是返回的这个函数执行了。

实际上可以看作是:

  1. 首先方法执行会返回一个函数,函数本身也是一个实例,所以在内部的处理中会给这个实例设置一个type属性,属性值不会和reducer中的逻辑进行匹配,所以不会造成任何状态的修改。
  2. 将返回的函数执行,把派发的方法dispatch传递给函数,在这个函数中,我们可以进行异步操作。当异步操作成功后,我们再手动基于传递进来的dispatch进行派发即可。

第二次派发:使用的dispatch其实是刚才我们手动传入函数的dispatch,这个dispatch才是store真正的dispatch方法。当在函数中异步成功后,我们在基于传递进来的这个真正的dispatch进行派发即可,此时会通知reducer执行,修改对应状态。

示例

js 复制代码
/* moduleAAction.js */
import * as TYPES from '../action-types'

const delay = (interval=3000) => {
   return new Promise(resolve=>{
     setTimeout(()=>{
       resolve()
     }, interval)
   })
 }


const moduleAAction = {
    // redux-thunk中间件的语法,
    adda(){ 
        return async (dispatch)=>{
            await delay()
            dispatch({ type:TYPES.moduleA_ADDA })
        }
        // return {type:TYPES.moduleA_ADDA} 
    }
    addb(){ return {type:TYPES.moduleA_ADDB} }
}

export default moduleAAction

但是每次异步派发的时候,都需要这样手动写这样的结构,还是不够方便,有没有更简单一点的?那接下来,我们来看 redux-promise中间件


promise中间件的使用及原理

使用

我们无需再手动修改actionCreator在编写时候的结构,只需要在actionCreator中,直接使用异步操作就可以,在异步操作后直接返回action对象即可。 使用上比thunk简单了不止一点半点。

redux-thunk的区别

其实两种中间件处理异步操作的原理都是一致的,都要派发两次,第一次派发的dispatch也是被重写的,区别在于它监听的是返回的promise实例,在实例成功后,基于真正的dispatch,把成功的结果再进行派发。而且第二次派发是其内部自动处理的。

原理

  1. 当我们触发交互,执行addb方法,dispatch会将moduleAAction.addb()执行

第一次派发的dispatch也是被重写的,是传递进来的promise实例,也没有type属性但不会报错,也不会通知reducer执行。

实际上可以看作是:

  1. 其内部会监听moduleAAction.addb()执行的返回值:【一个promise实例】等实例的状态变为成功时,其内部会再进行一次派发。这次派发用到的是store真正的dispatch方法,将会通知reducer执行。同时会将成功的结果【我们返回的action对象】传递给reducer,实现状态的修改

示例

js 复制代码
// 创建公共容器
import {createStore, applyMiddleware} from 'redux'
import reducer from './reducer'
import reduxLogger from 'redux-logger'
import reduxThunk from 'redux-thunk'
import reduxPromise from 'redux-promise' // 引入promise中间件

/*创建公共容器*/
const store = createStore(
    reducer,
    applyMiddleware(reduxLogger, reduxThunk, reduxPromise) //在创建公共容器时,通过applyMiddleware来注入并使用中间件,这里可以传入多个中间件
)

export defualt store
js 复制代码
/* moduleAAction.js */
import * as TYPES from '../action-types'

const delay = (interval=3000) => {
   return new Promise(resolve=>{
     setTimeout(()=>{
       resolve()
     }, interval)
   })
 }


const moduleAAction = {
    // redux-thunk中间件的语法
    adda(){ 
        return async (dispatch)=>{
            await delay()
            dispatch({ type:TYPES.moduleA_ADDA })
        }
        // return {type:TYPES.moduleA_ADDA} 
    }
    // redux-promise中间件的语法
    addb(){ 
        await delay()
        return {type:TYPES.moduleA_ADDB}
        // return {type:TYPES.moduleA_ADDB}
    }
}

export default moduleAAction

redux-thunkredux-promise的异同

相同点

  1. 都是用来处理异步派发的
  2. 都是派发两次
  3. 第一次派发都是使用重写过后的dispatch

第一次派发使用重写过的dispatch为的是避免校验对象是否具有type属性,也不会在乎传递的到底是不是标准的action对象。

  1. 第一次派发都是为了第二次(真正的)派发做准备

不同点

redux-thunk:把返回的函数执行,把真正的dispatch传递给函数

redux-thunk的第二次派发是手动处理的

redux-promise:监听返回的promise实例,在实例成功后,基于真正的dispatch,把成功的结果再进行派发

redux-promise的第二次派发是其内部自动处理的

相关推荐
我科绝伦(Huanhuan Zhou)5 分钟前
深入解析Shell脚本编程:从基础到实战的全面指南
前端·chrome
小马哥编程7 分钟前
React和Vue在前端开发中, 通常选择哪一个
前端·vue.js·react.js
aklry9 分钟前
uniapp实现在线pdf预览以及下载
前端·pdf·uni-app
℘团子এ31 分钟前
vue3中预览Excel文件
前端·javascript
shmily麻瓜小菜鸡1 小时前
在 Angular 中, `if...else if...else`
前端·javascript·angular.js
bloglin999992 小时前
npm和nvm和nrm有什么区别
前端·npm·node.js
2501_910227542 小时前
web3 前端常见错误类型以及错误捕获处理
前端·web3
哎哟喂_!3 小时前
Node.js 同步加载问题详解:原理、危害与优化策略
前端·chrome·node.js
__BMGT()3 小时前
C++ QT图片查看器
前端·c++·qt
未来之窗软件服务3 小时前
solidwors插件 开发————仙盟创梦IDE
前端·javascript·数据库·ide·仙盟创梦ide