Redux:中间件

redux中间件概念 比较容易理解。

在使用redux时,改变store state的一个固定套路是调用store.dispatch(action)方法,将action送到reducer中。

所谓中间件,就是在dispatch发送action  和  action到达reducer  之间,加入一些中间层,对action进行处理。

在之前学习redux的异步操作时,用到的redux-thunk就是一个中间件。action抵达reducer之前先对其进行判断,如果是对象就直接送到reducer;如果是函数就执行。

中间件特点:

1.是一个独立的函数,与其他中间件没有依赖关系

2.中间件可以有多个,按顺序组合使用

3.有统一的接口

中间件说白了就是一些第三方的插件,用来增强dispatch的功能,让我们可以在action到达reducer之前对action作出判断、改造、log下信息、实现复杂逻辑等。

当我们使用了多个中间件时,action依次从前一个中间件传到下一个中间件,最后抵达reducer。也可能在某个中间件进行处理后,发现没必要传到reducer了,就不传给下一个中间件(相当于丢弃,不再去处理)。

中间件必须定义为一个函数,它的基本结构如下:

1 function middleWare({dispatch,getState}){
2   return function(next){
3     return function(action){
4       return next(action)
5     }
6   }
7 }

中间件接收store的dispatch和getState方法

中间件返回一个接收next参数的函数,next参数自身是一个函数。中间件调用next函数告诉redux处理工作已经完成,将action传递给下一个中间件

中间件返回的函数(第二行),又返回一个带参数action的函数,这个函数里对action进行处理

我们可以发现中间件函数的设计,对函数进行了柯里化,遵循了函数式编程的思想。每个函数都有纯粹而明确的功能,通过嵌套组合实现更复杂的功能。

使用中间件:

1 import { createStore, applyMiddleware } from ‘redux‘;
2 import thunk from ‘redux-thunk‘;
3 import reducer from ‘./reducers‘
4
5
6 let store = createStore(
7      reducer,
8     applyMiddleware(thunk)
9     )

这是npm上redux-thunk文档给的使用使用该中间件的实例代码。使用中间件,需要用到redux的applyMiddleware方法。

在《深入浅出React和redux》一书中,作者倒是给出了两种使用中间件方式,代码不太一样:

1.针对简单场景:

1 import { createStore, applyMiddleware } from ‘redux‘;
2 import thunk from ‘redux-thunk‘
3
4 //这里applyMiddleware执行后产生的是一个Store Enhancer函数,
5 //Store Enhancer又将redux的createStore作为参数,生成一个加强版的创建store的函数
6 const configureStore = applyMiddleware(thunk)(createStore);
7 const store = configreStore(reducer,initialState);

这里的代码虽然跟上一段代码不太一样,但是其实逻辑是一样的。因为createStore的第三个参数就是一个Store Enhancer,当只有两个参数且第二个参数是函数时,就当作Enhancer。applyMiddleware(thunk)的执行结果就是一个Enhencer。

作者说“利用configureStore创造的store将具有中间件的功能”。效果是一样的。

2.针对使用其他Store Enhancer的场景,作者说,实际中我们常常会使用不止一种SE,所以更通常的情况是:用redux提供的compose方法将applyMiddleware的返回函数和其他SE组装成一个Store Enhancer,传入createStore中。

1 import { createStore, applyMiddleware,compose } from ‘redux‘;
2 import thunk from ‘redux-thunk‘
3
4 const win=window;
5 const storeEnhancer = compose(
6   applyMiddleware(...middlewares),
7  (win && win.devToolsExtension)?win.devToolsExtension():f=>f);
8 );
9 const store = creatorStore(reducer,storeEnhancer);

其中applyMiddleware必须作为compose的第一个参数,因为中间件的顺序也是它们处理action的顺序,其他SE如果不能识别action,会报错。

中间件实现:

 1 function isPromise(obj){
 2   return obj && typeof obj.then === ‘fuction‘
 3 }
 4
 5 export default function PromiseMiddleware((dispatch)){
 6   return function(next){
 7     return function(action){
 8       return isPromise(action)?action.then(dispatch):next(action);
 9
10     }
11   }
12 }

这是书上的一个未改进的例子,redux中某一类型的函数总有固定的套路。这段代码判断action是否promise,并执行对应操作。遵循着MiddleWare=>(next)=>(action)=>{next(action)}的套路。

程墨强调,开发中间件时要记住两个原则:

1.中间件应该独立存在,在功能和顺序上不依赖于其他中间件

2.应该考虑到当前有多个中间件存在,要通过next(action)将action交还给中间件管道

Store Enhancer:

中间件可以定制增强dispatch方法,但也只是对于dispatch方法。要增强store,需要使用store enhancer。applyMiddleware的返回值其实就是个SE,通过SE可以增强store的各个方面。

我们知道createStore方法接收三个参数(reducer,initialState,storeEnhancer).storeEnhancer是一个函数,接收createStore模样的函数作为参数,返回一个新的createStore。

 1 //一个什么都不做的SE
 2 const doNothingSE = (createStore)=>(reducer,preState,enhancer)=>{
 3   const store = createStore(reducer,preState,enhencer);
 4   return store;
 5 };
 6 //每次dispatch都log下action的SE
 7 const doNothingSE = (createStore)=>(reducer,preState,enhancer)=>{
 8   const store = createStore(reducer,preState,enhencer);
 9   const originDispatch = store.dispatch;
10   store.dispatch=(action)=>{
11     console.log(‘dispatch action: ‘ + action );
12     originDispatch(action);
13   }
14   return store;
15 };

可以看出,SE的基本套路是将原来的成员函数的引用保存下来,然后写一个新的实现,在新的实现里添加额外功能代码,然后调用原来的成员函数,从而达到扩展功能的目的。

出了增强原有方法的功能外,还可以给store添加新方法,比如在函数体内定义一个newMethod,return {...store,newMethod};

时间: 2024-11-05 02:23:26

Redux:中间件的相关文章

redux中间件

怎么自定义一个中间件呢? 根据 redux 文档,中间件的签名如下: ({ getState, dispatch }) => next => action 根据上文的 applyMiddleware 源码,每个中间件接收 getState & dispatch 作为参数,并返回一个函数,该函数会被传入下一个中间件的 dispatch 方法,并返回一个接收 action 的新函数. 以一个打印 dispatch action 前后的 state 为例,创建一个中间件示例: export

react+redux教程(七)自定义redux中间件

教程源代码及目录 https://github.com/lewis617/myReact 今天,我们要讲解的是自定义redux中间件这个知识点.本节内容非常抽象,特别是中间件的定义原理,那多层的函数嵌套和串联,需要极强逻辑思维能力才能完全消化吸收.不过我会多罗嗦几句,所以不用担心. 例子 例子是官方的例子real-world,做的是一个获取github用户.仓库的程序. 本例子源代码: https://github.com/lewis617/myReact/tree/master/redux-e

Redux中间件随笔

说到Redux中间件,我见到的他的应用,在一个高星项目中,是做数据的异步获取,后端接口调用的角色.我甚感此种方式的精明之处.在此写个文章,任诸君品鉴,若有不到之处,不吝赐教. 1.什么是中间件?既然叫了中间件,就有中间件的共性.Express中中间件,就是一个拦截的作用,每次的request,都会被所截获,然后做你想要做的目的.如果你想放行,就next();继续下个中间件.同理Redux中,request=>action,request变成了action.其他就是一样的.每个触发action都会

redux中间件和redux-thunk实现原理

redux-thunk这个中间件可以使我们把这样的异步请求或者说复杂的逻辑可以放到action里面去处理,redux-thunk使redux的一个中间件,为什么叫做中间件 我们说中间件,那么肯定是谁和谁的中间,那么redux的中间件指的是谁和谁的中间呢? 如图.view在redux中会派发一个action,action通过store的dispatch方法派发给store,store接收到action,连同之前到state,一起传给reducer,reducer返回一个新到数据给store,sto

浅谈redux 中间件的原理

在使用redux管理异步数据流的时候,我们会使用中间件,以redux-thunk中间件为例,我们做一下分析: 首先是构建store,我们需要以下代码进行揉入中间件的类似creatStore函数的构造: const loggerMiddleware = createLogger(); const createStoreWithMiddleware = applyMiddleware( thunkMiddleware, loggerMiddleware )(createStore); export

redux中间件的原理——从懵逼到恍然大悟

前言react已经出来很久了,其生态圈之庞大,一锅炖不下!各种react-xx,已让我们不堪重负,github上随便一个demo,引入的模块至少都是五指之数+.看着头疼,嚼之无味…….在此建议新学者,可以从基础的核心模块学起,前期不要考虑那些数量繁多的马仔小弟,边学边写,个人感觉前期核心要学的流程大致如下:React ——> React + redux + React-redux ——> React + redux + React-redux + React-router ——> Rea

Redux 中间件和异步操作

回顾一下Redux的数据流转,用户点击按钮发送了一个action,  reducer 就根据action 和以前的state 计算出了新的state, store.subscribe 方法的回调函数中 store.getState() 获取新的state, 把state 注入到页面元素中,实现页面状态的更新.你发现根本就没有机会去做一个异步的操作,那怎么办? 现实世界中有大量的异步操作,那要用到Redux 的新的工具:中间件. 中间件,说白了,就是中间的部分,正常的流程中,先执行函数a,然后执行

理解redux中间件

redux questions : 1. reducers 函数如何创建和聚合 2. action创建函数如何如何包裹在dispatch函数中 3. 如何给默认的dispatch方法增加中间件能力 middleware: (js context)中间件由函数组合的形式创建,实现与主要执行任务正交的功能. tips:类似的有装饰器模式 在 redux middleware 要装饰的主要功能是 dispatch 函数.dispatch 函数的主要功能是发送actions 给 reducer函数来产生

Redux 中间件的执行顺序理解

Redux.applyMiddleware(thunk, middleware1) 和 Redux.applyMiddleware(middleware1, thunk) 的区别: <!DOCTYPE HTML> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Redux<