redux中间件原理及实现
程序员文章站
2023-11-02 19:37:46
redux中间件原理及实现
先看下面最简单的redux使用例子
import { createstore, applymiddleware, compose } from 'redux&...
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简化后就是, 接受两个参数dispatch和 getstate, 返回一个函数,继续调用则会传入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实现的功能, 在有异步请求的时候,应该返回一个函数,比如下面, 这就可以在里面继续使用dispatch和getstate了,真是煞费苦心啊,就为了实现代码隔离的时候还能够使用redux里面的dispatch和getstate来获取状态和触发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,生成每个中间件都需要的dispatch和getstate, 接着重点来了,遍历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))) }
上一篇: webpack热加载原理探索