redux中间件原理及实现

最近看跟react相关库的源码,越来越发现里面中间件机制的特别重要,各种类库都是基于此封装的功能,比如redux简单的几个函数,却巧妙的实现了中间件创建,组合,调用,下面就一一分析

先看下面最简单的redux使用例子

import { createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import reducers from './reducer'

const store = createStore(reducers, compose(
    applyMiddleware(thunk),
    window.devToolsExtension ? window.devToolsExtension() : f => f
))

创建中间件

我们从最里面看,这里的thunk就是个满足redux的中间件实现,打开源码看看,createThunkMiddleware利用函数柯里化的特性缓存了三层参数变量,后面调用了才暴露出去的,所以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;

thunk简化后就是, 接受两个参数dispatchgetState, 返回一个函数,继续调用则会传入next就是真正的dispatch的, 这里action一般都是一个对象,比如{type: AUTH_SUCCESS, payload:data}, 就用dispatch(action)去触发变更组件,但是这个中间件判断了一下action是函数function的时候,会调用这个函数,然后把参数传进去

function thunk ({ dispatch, getState }) {
   return next => actioin => {
      if (typeof action === 'function') {
         return action(dispatch, getState);
      }
      return next(action);
  }
}

那么action是函数的时候是怎么样的呢,这就是reudx-thunk实现的功能, 在有异步请求的时候,应该返回一个函数,比如下面, 这就可以在里面继续使用dispatchgetState了,真是煞费苦心啊,就为了实现代码隔离的时候还能够使用redux里面的dispatchgetState来获取状态和触发action实现更新组件

export function login({user, pwd}) {
    return (dispatch, getState) => {
        axios.post('/user/login', {user, pwd})
        .then(res=>{
            if (res.status === 200 && res.data.code === 0){
                dispatch(authSuccess(res.data.data))
            } else {
                dispatch(errorMsg(res.data.msg))
            }
        })
    }
}

使用中间件

上面搞清楚了中间件的创建,那么怎么使用呢,这下就要看applyMiddleware这个函数了,代码如下,也没有几行,可是信息量很大啊,整体来看又是柯里化来保存参数,证明如果有中间件的话,会传入createStore,在这里面构建store,生成每个中间件都需要的dispatchgetState, 接着重点来了,遍历middlewares中间件数组,分别调用每个中间件一次

export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    const store = createStore(reducer, preloadedState, enhancer)
    let dispatch = store.dispatch
    let chain = []
    const middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)
    return {
      ...store,
      dispatch
    }
  }
}
export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }
  if (funcs.length === 1) {
    return funcs[0]
  }
  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}



作者:Jason_Zeng
链接:https://www.jianshu.com/p/8c2a37247020
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值