美文网首页
理解Redux异步操作之redux-thunk中间件!

理解Redux异步操作之redux-thunk中间件!

作者: YouthInXian | 来源:发表于2019-02-21 19:43 被阅读0次

    前言

    最近写个人博客的时候,想要找一种优雅的方式管理项目中的API请求,于是找到了redux-promise这样的中间件,之前有在Redux中文文档中学习过中间件,但是并未真正理解,只是简单的学会了applyMiddleware(reducer,thunk)这样去使用。

    借这次机会,认真理解一番redux-thunk中间件的原理,希望能帮到对redux-thunk工作原理感兴趣的同学。

    本文适合有redux middleware基础的同学阅读。

    博主也是个努力成长中的前端小白,这算是第一篇自己的博客(#害羞),还请各位看官佬爷批评指正。

    redux-thunk作用

    没有中间件的时候,action只能是包含type的普通js对象,redux-thunk就是为了让redux看到,异步Action-Creator可以作为正常的动作创建者的特例而不是完全不同的函数,是redux异步action实现的解决方案之一。

    咳咳,有点官方了,简单来说,就是为了能让你dispatch一个函数。

    我们知道redux的中间件是工作在action发起之后,达到reducer之前的扩展点(不知道的请先移步至Redux中文文档),因此它更加本质的作用是‘强化’/‘改造’dispatch函数。这也是它为什么能使dispatch接收一个函数作为参数的原因。

    简单使用

    import { createStore, applyMiddleware } from 'redux'
    import rootReducer from './rootReducers'
    import thunkMiddleWare from 'redux-thunk'
    
    const store = createStore(rootReducer, applyMiddleware(thunk))
    

    理解

    在创建store的时候,我们调用了applyMiddleware(thunk),这里其实已经将dispatch方法强化过了。再通过Provider组件分发给各个容器组件之后,后续所有使用的store.dispatch都已经是改造过的dispatch,为了方便理解,我把核心代码放在一起。

    // redux-thunk源码核心
    function createThunkMiddleware(extraArgument) {
      return ({ dispatch, getState }) => next => action => {
        if (typeof action === 'function') {
          return action(dispatch, getState, extraArgument);
        }
        // 调用强化之前的dispatch
        return next(action);
      };
    }
    const thunk = createThunkMiddleware();
    export default thunk;
    
    --------------------------------------------分割线----------------------------------------------
    
    // 理想化的applyMiddleware源码
    // 这不是官方的API,只是为了便于理解,可以发现与官方的函数签名不一致
    function applyMiddleware(store, middlewares) {
      ...
      let dispatch = store.dispatch
      middlewares.forEach(middleware =>
        dispatch = middleware(store)(dispatch)
      )
      return Object.assign({}, store, { dispatch })
    }
    
    --------------------------------------------分割线-----------------------------------------------
    // 将中间件应用到store中
    const storeWithMiddleware = applyMiddleware(store, [thunk])
    

    调用applyMiddleware()它会遍历一个个中间件,并且调用它两次。thunk其实就是一个多层嵌套的函数, 通过thunk(store)(dispatch)调用之后会返回一个函数,并将其赋值给dispatch,也就是说应用了中间件之后,store.dispatch变成了类似这个样子:

    const dispatch = action => {
        // 注意:async function() {} 用typeof判断, 结果也是'function'
        if (typeof action === 'function') {
          // 调用该函数,并传递参数
          return action(dispatch, getState, extraArgument);
        }
        
        return next(action);
    };
    

    在此之后所有通过dispatch派发的action都会经过上述中间件。如果action是函数,则调用它并传递参数。

    在此基础上理解一个action从调用被派发到执行的过程。
    当你派发一个异步的action,你会这样写:

    UIComponent.js

    classes Contact extends React.Component {
      render () {
        return <div>
              ...
              ...
            <Button onClick={this.handleSend}>Contact</Button>
        </div>
      }
      handleSend = () => {
        this.props.contactAuthor()
      }
    }
    

    actionCreators.js

    export const contactAuthor = (info) => async (dispatch, getState) => {
        const result = await postData(`${messageUrl}/contact`, info)
        if (result) {  dispatch...}
        else {  dispatch... })
        }
    }
    

    ContactContainers.js

    const mapDispatchToProps = (dispatch) => {
     // 简单实现
     // return {
      //   contactAuthor:(info) => {
      //     这里dispatch的参数是actionCreator的返回值,异步action函数
      //     dispatch(contactAuthor(info))
      //   }
      // }
      return bindActionCreators({
        contactAuthor
      }, dispatch)
    }
    const aboutMeContainers = connect(null, mapDispatchToProps)(Contact)
    

    当点击该按钮后,调用容器组件赋予的contactAuthor()方法,也就是dispatch(contactAuthor()), dispatch的参数是contactAuthor()的返回值。也就是dispatch了一个异步函数式的action,也就是调用了改造后的dispatch函数,不懂的同学请看注释。

    1.将dispatch,getState,args作为action的参数
    2.调用action(dispatch, getState, args)
    3.异步action运行

    结语

    这算是我的第一篇博客。。可能写的有点懵,但还是希望有人看到这里能茅塞顿开,对redux-thunk以及异步中间件的整个运行过程能更好地掌握。

    谢谢!

    相关文章

      网友评论

          本文标题:理解Redux异步操作之redux-thunk中间件!

          本文链接:https://www.haomeiwen.com/subject/isddyqtx.html