美文网首页
2-Redux中间件

2-Redux中间件

作者: 我竟无言以对_1202 | 来源:发表于2021-02-25 21:47 被阅读0次

    Redux 中间件

    [toc]

    Redux 中间件的作用

    Reudx 中的中间件是通过对 dispatch 进行的二次封装,对 action 发起之后,reducer 调用之前的行为进行扩展,我们可以通过中间件来进行:日志记录发送报告调用异步接口 ……

    从日志记录需求开始

    需求:再每次 dispatch 的时候打印修改之前和之后的 state

    准备

    let initState = {
      users: []
    }
    
    function reducers(state=initState, {type, payload}) {
      switch(type) {
        case 'user/add':
          return Object.assign(state, {
            users: [...state.users, payload]
          });
      }
    
      return state;
    }
    
    let store = Redux.createStore(
      reducers
    );
    

    最直接最原始的做法

    console.log(store.getState());
    store.dispatch({
      type: 'user/add',
      payload: 'zmouse'
    });
    console.log(store.getState());
    

    封装 logger

    function logger(store, action) {
      console.log(store.getState());
      store.dispatch(action)
      console.log(store.getState());
    }
    
    logger(store, {
      type: 'user/add',
      payload: 'zmouse'
    });
    

    封装 dispatch

    let next = store.dispatch;
    store.dispatch = function logger(action) {
      console.log(store.getState());
      next(action);
      console.log(store.getState());
    }
    
    store.dispatch({
      type: 'user/add',
      payload: 'zmouse'
    });
    

    添加错误报告发送

    需求:每次 dispatch 把提交的数据进行持久化

    let next = store.dispatch;
    store.dispatch = function storage(action) {
      next(action);
      let s = localStorage
    }
    
    store.dispatch({
      type: 'user/add',
      payload: 'zmouse'
    });
    

    封装合并多个中间件

    • 把每个独立的中间件封装成独立的函数
    • 每个中间件都需要获取一次 dispatch
    function logger(store) {
      let next = store.dispatch;
      return function loggerDispatch(action) {
        console.log('before: ', store.getState());
        next(action);
        console.log('after: ', store.getState());
      }
    }
    
    function storage(store) {
      let next = store.dispatch;
      return function storageDispatch(action) {
        next(action);
        localStorage.setItem('store', JSON.stringify(store.getState()));
        console.log('持久存储完成');
      }
    }
    
    store.dispatch = logger(store);
    store.dispatch = storage(store);
    
    store.dispatch({
      type: 'user/add',
      payload: 'zmouse'
    });
    

    方法一个方法统一处理中间件函数的注册

    封装一个 applyMiddleware 方法

    function applyMiddleware(store, middlewares) {
      middlewares.reverse()
      middlewares.forEach(middleware => {
        store.dispatch = middleware(store)
      })
    }
    
    applyMiddleware(store, [logger, storage])
    

    抽取 next

    function applyMiddleware(store, middlewares) {
      middlewares.reverse()
      let dispatch = store.dispatch
      middlewares.forEach(middleware => {
        dispatch = middleware(store)(dispatch)
      })
      store.dispatch = dispatch;
    }
    
    function logger(store) {
      return function(next) {
        return function loggerDispatch(action) {
          console.log('before: ', store.getState());
          next(action);
          console.log('after: ', store.getState());
        }
      }
    }
    
    function storage(store) {
      return function(next) {
        return function storageDispatch(action) {
          next(action);
          localStorage.setItem('store', JSON.stringify(store.getState()));
          console.log('持久存储');
        }
      }
    }
    

    ES6 改写

    let logger = store => next => action => {
      console.log('before: ', store.getState());
      next(action);
      console.log('after: ', store.getState());
    }
    let storage = store => next => action => {
      next(action);
      localStorage.setItem('store', JSON.stringify(store.getState()));
      console.log('持久存储');
    }
    

    使用 Redux.applyMiddleware 方法

    Redux 内置了一个 applyMiddleware 方法用来注册中间件

    let store = Redux.createStore(
      reducers,
      Redux.applyMiddleware(logger, storage)
    );
    

    异步的问题

    仔细观察我们发现,默认的 dispatch 是没有对异步的任务进行处理的,且该方法默认情况下接收的是一个 action 对象

    redux-thunk 的原理

    通过中间件重新封装 dispatch 方法,使它能够接收一个异步任务函数

    let thunk = store => next => action => {
      console.log('thunk');
      new Promise( (resolve, reject) => {
        action(next);
      } )
    }
    
    store.dispatch( dispatch => {
      setTimeout(() => {
        dispatch({
          type: 'user/add',
          payload: 'zmouse'
        });
      }, 1000);
    } )
    

    相关文章

      网友评论

          本文标题:2-Redux中间件

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