Redux学习笔记-中间件与异步操作

时间:2021-05-26 20:01:26

参考:http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.html

  • 中间件概念
    中间件是一个函数,对store.dispatch方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能,使得能 Reducer 在异步操作结束后自动执行。
  • 常见中间件的用法
    • redux-logger
      import { applyMiddleware, createStore } from 'redux';
      import createLogger from 'redux-logger';
      const logger = createLogger();
      
      const store = createStore(
        reducer,
        applyMiddleware(logger)
      );

      上面代码中,redux-logger提供一个生成器createLogger,可以生成日志中间件logger。然后,将它放在applyMiddleware方法之中,传入createStore方法,就完成了store.dispatch()的功能增强。

    • redux-thunk
      store.dispatch方法正常情况下,参数只能是对象,不能是函数。
      import { createStore, applyMiddleware } from 'redux';
      import thunk from 'redux-thunk';
      import reducer from './reducers';
      
      // Note: this API requires redux@>=3.1.0
      const store = createStore(
        reducer,
        applyMiddleware(thunk)
      );

      上面代码使用redux-thunk中间件,改造store.dispatch,使得后者可以接受函数作为参数。

      因此,异步操作的第一种解决方案就是,写出一个返回函数的 Action Creator,然后使用redux-thunk中间件改造store.dispatch

    • redux-promise
      import { createStore, applyMiddleware } from 'redux';
      import promiseMiddleware from 'redux-promise';
      import reducer from './reducers';
      
      const store = createStore(
        reducer,
        applyMiddleware(promiseMiddleware)
      ); 

      这个中间件使得store.dispatch方法可以接受 Promise 对象作为参数。

  • redux-applyMiddleware()
    它是 Redux 的原生方法,作用是将所有中间件组成一个数组,依次执行。下面是它的源码。
    export default function applyMiddleware(...middlewares) {
      return (createStore) => (reducer, preloadedState, enhancer) => {
        var store = createStore(reducer, preloadedState, enhancer);
        var dispatch = store.dispatch;
        var chain = [];
    
        var middlewareAPI = {
          getState: store.getState,
          dispatch: (action) => dispatch(action)
        };
        chain = middlewares.map(middleware => middleware(middlewareAPI));
        dispatch = compose(...chain)(store.dispatch);
    
        return {...store, dispatch}
      }
    }