博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
redux-applyMiddleware实现理解+自定义中间件
阅读量:4085 次
发布时间:2019-05-25

本文共 3908 字,大约阅读时间需要 13 分钟。

前言:

http://www.cnblogs.com/miaowwwww/p/6265323.html

  终于好好理解了middleware。。。。

1.redux middleware提供的是位于 action 被发起之后,到达 reducer 之前的扩展点。

  redux通过store.dispatch(atcion),发起一个action给store,store接收后把当前state与action一起传给reducer,所以middleware做文章的地方就是dispatch,在原生的dispatch执行之前,先进行一些列的操作。

 

实现middleware的方法:下面以logger中间件为例

1.手动记录(不可能会使用这种的吧)

let action = addTodo('Use Redux')console.log('dispatching', action)store.dispatch(action)console.log('next state', store.getState())

 

2.封装dispatch

  要发起action的时候,不用 dispatch 而是用 disptchAddLog()。(把这个方法放在store里面、好像还不错的样子)

function dispatchAndLog(store, action) {  console.log('dispatching', action)  store.dispatch(action)  console.log('next state', store.getState())}

 

3.猴子补丁

  通过重写store.dispatch(), (重写之后,所使用的dispatch(), 已经不是原生的dispatch了,使用多个中间件,就是不断改写前一次生成的dispatch),

  (注意:原生的dispatch,已经不可能找到,也就是不能单独使用原始dispatch了)

function(store) {    let next = store.dispatch    store.dispatch = function dispatchAndLog(action) {        console.log('dispatching', action)        let result = next(action)        console.log('next state', store.getState())        return result    }}

 

 

4.隐藏猴子补丁,

  乍一看好像和猴子补丁没什么却别,但其实它把赋值的给store.dispatch的逻辑放到了中间件函数的外面,需要外面提过一个applyMiddleware辅助函数来完成插值,除此之外,真的没什么区别。(原理还是猴子补丁)

function logger(store) {  let next = store.dispatch  // 我们之前的做法:  // store.dispatch = function dispatchAndLog(action) {
return function dispatchAndLog(action) { console.log('dispatching', action) let result = next(action) console.log('next state', store.getState()) return result }}

 

  多个中间件 的实现方式:

function applyMiddlewareByMonkeypatching(store, middlewares) {  middlewares = middlewares.slice()  middlewares.reverse()  // 在每一个 middleware 中变换 dispatch 方法。  middlewares.forEach(middleware =>    store.dispatch = middleware(store)  )}

 

5.移除猴子补丁

  相对隐藏猴子不同,把middleware函数里面 let next = store.dispatch ,放到函数外面 dispatch = middleware(store)(dispatch) 

function logger(store) {  return function wrapDispatchToAddLogging(next) {    return function dispatchAndLog(action) {      console.log('dispatching', action)      let result = next(action)      console.log('next state', store.getState())      return result    }  }}

 

  看一下多个中间件实现方式你就知道了,

  是否发现:在 return 的 assign 之前, store.dispatch 都是原生的,并没有被改变。所以中间件里面是否可以使用store.dispatch调用原生的,(如果有需要的话),然而笔者试着调用了一下,并不行,会不断的触发,就是已经是该改变之后的了。

// 警告:这只是一种“单纯”的实现方式!// 这 *并不是* Redux 的 API.function applyMiddleware(store, middlewares) {  middlewares = middlewares.slice()  middlewares.reverse()  let dispatch = store.dispatch  middlewares.forEach(middleware =>    dispatch = middleware(store)(dispatch)  )  return Object.assign({}, store, { dispatch })}

 

  logger中间件换成es6的箭头函数更好看

const logger = store => next => action => {  console.log('dispatching', action)  let result = next(action)  console.log('next state', store.getState())  return result}

 

 

6.redux中是现实方法

这与 Redux 中  的实现已经很接近了,但是有三个重要的不同之处

  • 它只暴露一个  的子集给 middleware: 和 。

  • 它用了一个非常巧妙的方式来保证你的 middleware 调用的是 store.dispatch(action) 而不是 next(action),从而使这个 action 会在包括当前 middleware 在内的整个 middleware 链中被正确的传递。这对异步的 middleware 非常有用。

  • 为了保证你只能应用 middleware 一次,它作用在 createStore() 上而不是 store 本身。因此它的签名不是 (store, middlewares=> store, 而是 (...middlewares=(createStore=> createStore

 

总结:

  redux提供了applyMiddleware(), 如果我们自定义中间件,也就变的很简单了

function myMiddleware = (store) => (next) => (action) => {    console.log('进入了我自己定义的中间件');    let result = next(action);    // 执行下一步    // let result = store.dispatch(action); //不调用next,直接使用store.dispatch调用原生。然后是不行的,会陷入dispatch死循环。    return result;}

  applyMiddleware会帮我们执行前面两层函数。myMiddleware(store)(dispatch)

redux-thunk的实现也是很牛掰

function createThunkMiddleware(extraArgument) {  return ({ dispatch, getState }) => next => action => {    if (typeof action === 'function') {      return action(dispatch, getState, extraArgument);    }    return next(action);  };}const thunk = createThunkMiddleware();thunk.withExtraArgument = createThunkMiddleware;export default thunk;
你可能感兴趣的文章
Nginx篇-Nginx配置动静分离
查看>>
缓存篇-Redis缓存失效以及解决方案
查看>>
缓存篇-使用Redis进行分布式锁应用
查看>>
缓存篇-Redisson的使用
查看>>
phpquery抓取网站内容简单介绍
查看>>
找工作准备的方向(4月22日写的)
查看>>
关于fwrite写入文件后打开查看是乱码的问题
查看>>
用结构体指针前必须要用malloc,不然会出现段错误
查看>>
Linux系统中的美
查看>>
一些实战项目(linux应用层编程,多线程编程,网络编程)
查看>>
我觉得专注于去学东西就好了,与世无争。
查看>>
原来k8s docker是用go语言写的,和现在所讲的go是一个东西!
查看>>
STM32CubeMX 真的不要太好用
查看>>
STM32CubeMX介绍、下载与安装
查看>>
不要买铝合金机架的无人机,不耐摔,易变形弯曲。
查看>>
ACfly也是基于FreeRTOS的
查看>>
F330装GPS的位置
查看>>
pixhawk也可以用Airsim仿真
查看>>
《无人机电机与电调技术》可以看看
查看>>
我发现七月在线的GAAS课程基本都讲到了
查看>>