redux-thunk引发的redux middleware和store enhancer浅析

2019-12-03 18:07:11 浏览数 (1)

本文作者:IMWeb EnjoyChan 原文出处:IMWeb社区 未经同意,禁止转载

项目中使用redux-thunk来解决异步请求的问题,但是为什么要引入redux-thunk来解决异步请求问题,不借助redux-thunk就无法解决吗?

代码语言:javascript复制
以setTimeout dispatch场景为例,在异步执行时dispatch action就可以实现了

// 1

store.dispatch({

  type: 'BEFORE_ASYNC'

})

setTimeout(() => {

  store.dispatch({

    type: 'DOING_ASYNC'

  })

}, 0)

既然可以简单两步解决,那么为什么还需要引入redux-thunk, 或者说redux-thunk可以解决什么场景问题;来看下面这个场景,我们上面那份代码可能被多次调用,根据传入参数来执行,于是我们封装一个函数:

代码语言:javascript复制
// 2

function encapsulateFunc(dispatch, data) {

  dispatch({

    type: 'BEFORE_ASYNC'

  })



  setTimeout(() => {

    dispatch({

      type: 'DOING_ASYNC',

      data

    })

  }, 0)

}

// 调用
encapsulateFunc(store.dispatch, {data: '2'});

第二种

代码语言:javascript复制
// 3

// 传入依赖
import store from './store';

function encapsulateFunc(data) {

  store.dispatch({

    type: 'BEFORE_ASYNC'

  })



  setTimeout(() => {

    store.dispatch({

      type: 'DOING_ASYNC',

      data

    })

  }, 0)

}

// 调用
encapsulateFunc({data: '3'});

对比上面封装函数的两种方法我们可以看出:

  1. 第一种方法, 每次调用的时候都传入dispatch参数,十分冗余
  2. 第二种方法,植入store依赖,方法依赖于store,这使得代码的迁移性并不友好

鉴于上述,我们再来看看使用redux-thunk,我们可以如何实现

代码语言:javascript复制
function encapsulateFunc(data) {

  return (dispatch) => {

    dispatch({

      type: 'BEFORE_ASYNC'

    })



    setTimeout(() => {

      dispatch({

        type: 'DOING_ASYNC',

        data

      })

    }, 0) 

  }

}

store.dispatch(encapsulateFunc({data: '4'}))

ecncapsulateFunc是一个action creator,不需要关心同步还是异步,返回的是对象还是函数,只需要关注传入的参数; 观察ecncapsulateFunc,我们会发现它返回了一个函数,参数传入dispatch,我们称ecncapsulateFunc为thunk函数,关于thunk不了解的可以戳链接http://www.ruanyifeng.com/blog/2015/05/thunk.html;

对比上述,使用redux-thunk可以帮助我们代码更优雅,封装设计更合理,当然redux-thunk是在我们需要的时候才引入,如果我们的实际项目明明可以简单解决,就不需要引入redux-thunk了。

middleware与store enhancer

redux-thunk是一个redux middleware,redux引入middleware方式如下:

代码语言:javascript复制
import { createStore, applyMiddleware } from 'redux';

import thunkMiddleware from 'redux-thunk';

import reducer from './reducer';

const middleware = applyMiddleware(thunkMiddleware);

const store = createStore(

  reducer,

  window.initialState,

  middleware

)

将applyMiddlewarer方法执行的返回结果传入createStore第三个参数,那么applyMiddleware方法执行后返回了什么呢,查看redux官方文档,看到createStore的使用如下:

createStore(reducer, [preloadedState], [enhancer])

第三个参数enhancer可选,也就是说applyMiddleware方法返回了一个enhancer,这里的enhancer就是store enhancer, 所谓的enhancer就是增强原有的功能,正如middleware, redux-thunk通过包裹改造dispatch, 使得dispatch方法可以接受函数类型的参数,增强了dispatch的功能;而store,我们知道store有四个属性方法dispatch、getState、subscribe、replaceReducer,通过改造增强这些方法 ,也就可以enhance store, 一个store enhancer大概长这样:

代码语言:javascript复制
function storeEnhancerCreator() {
  return createStore => (reducer, initialState, enchancer) => {
    var store = createStore(reducer, initialState);
    // do somethiing to enhance store here
         return store;
  }
}

基本上拓展功能使用middleware, 但如果有些场景需要改造store,可以试试通过创建一个store enhancer。

0 人点赞