欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

redux中间件原理及实现

程序员文章站 2022-06-08 20:39:08
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)))
}