资讯专栏INFORMATION COLUMN

redux中间件原理

jollywing / 2313人阅读

摘要:中的是实际的调用顺序是和传入中间件顺序相反的实际的执行是次序是。这个返回的函数是中倒数第二个函数的参数,也就是参数源码参考

中间件执行顺序

应用了如下的中间件: [A, B, C],

整个执行 action 的过程为 A -> B -> C -> dispatch -> C -> B -> A

==经过applyMiddleware方法后的dispatch方法是类似下面,某处调用store.dispatch则传入action, 然后按洋葱模型来执行==

(action) => {
    //...
    next(action)
    //...
}

==最右侧的 next(action)返回的是应用传入的action==, 该行为是由redux createStore源码中dispatch方法返回值决定的,不过一般都会 return next(action),

前面的中间件的next(action)的值都是后一个中间件的返回值

小例子
const middleware1 = ({getState, dispatch}) => next => action => {

    console.log(`middleware1 before next action `)
    console.log(next)
    next(action)
    console.log(`middleware1 after next action `)
}
const middleware2 = ({getState, dispatch}) => next => action => {

    console.log(`middleware2 before next action `)
    console.log(next)
    next(action)
    console.log(`middleware2 after next action `)
}
const middleware3 = ({getState, dispatch}) => next => action => {

    console.log(`middleware3 before next action `)
    console.log(next)
    next(action)
    console.log(`middleware3 after next action `)
}



const sagaMiddleware = createSagaMiddleware()
const store = createStore(reducer, applyMiddleware(middleware1, middleware2, middleware3))

被中间件包装过的dispatch方法

是类似于func1(func2(store.dispatch))这种形式的函数

==next方法其实是此中间件右边中间件的这个方法,你要给它传action。==

(action) => {
    //func2中的next是store.dispatch
    next(action);
}

==实际的调用顺序是和传入中间件顺序相反的==

let store = applyMiddleware(Middleware1,Middleware2,Middleware3)(createStore)(rootReducer);

实际的执行是次序是store.dispatch->Middleware3->Middleware2->Middleware1。
middlewareAPI中的dispatch被普通函数包装了一下

var middlewareAPI = {

getState: store.getState,
dispatch: (action) => dispatch(action)

};

并没有直接使用dispatch:dispatch,而是使用了dispatch:(action) => dispatch(action),其目的是==如果使用了dispatch:dispatch,那么在所有的Middleware中实际都引用的同一个dispatch(闭包),如果存在一个中间件修改了dispatch,就会导致后面一下一系列的问题==,但是如果使用dispatch: (action) => dispatch(action)就可以避免这个问题。

compose源码
export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  const last = funcs[funcs.length - 1]
  const rest = funcs.slice(0, -1)
  return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
}



applyMiddleware 源码

这里chain是函数数组。然后执行compose(...chain)(store.dispatch)。
chain数组的最后一个函数接收store.dispatch函数做为参数,还是返回一个函数,接收action作为参数。这个返回的函数是chain中倒数第二个函数的参数,也就是参数next

[
    next => action => {
        
        return next(action)
    }
]

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
    }
  }
}
redux-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;
参考

https://github.com/MrErHu/blo...

https://zhuanlan.zhihu.com/p/...

https://zhuanlan.zhihu.com/p/...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93720.html

相关文章

  • Redux原理分析

    摘要:调用链中最后一个会接受真实的的方法作为参数,并借此结束调用链。总结我们常用的一般是除了和之外的方法,那个理解明白了,对于以后出现的问题会有很大帮助,本文只是针对最基础的进行解析,之后有机会继续解析对他的封装 前言 虽然一直使用redux+react-redux,但是并没有真正去讲redux最基础的部分理解透彻,我觉得理解明白redux会对react-redux有一个透彻的理解。 其实,...

    sumory 评论0 收藏0
  • Redux间件原理详解

    摘要:当你应用了中间件,在触发一个操作的时候,操作就会经过先经过中间件,最终再形成。以其中两个中间件为例,说明下,一个触发一个动作的时候,代码的执行逻辑。 为了解析中间件,先看一下几个中间件是什么样子,怎么用,运行起来的原理是什么? 1、中间件是什么样子的 1.2 thunk中间件 function createThunkMiddleware(extraArgument) { retu...

    Shihira 评论0 收藏0
  • React专题:react,redux以及react-redux常见一些面试题

    摘要:我们可以为元素添加属性然后在回调函数中接受该元素在树中的句柄,该值会作为回调函数的第一个参数返回。使用最常见的用法就是传入一个对象。单向数据流,比较有序,有便于管理,它随着视图库的开发而被概念化。 面试中问框架,经常会问到一些原理性的东西,明明一直在用,也知道怎么用, 但面试时却答不上来,也是挺尴尬的,就干脆把react相关的问题查了下资料,再按自己的理解整理了下这些答案。 reac...

    darcrand 评论0 收藏0
  • React 328道最全面试题(持续更新)

    摘要:希望大家在这浮夸的前端圈里,保持冷静,坚持每天花分钟来学习与思考。 今天的React题没有太多的故事…… 半个月前出了248个Vue的知识点,受到很多朋友的关注,都强烈要求再出多些React相前的面试题,受到大家的邀请,我又找了20多个React的使用者,他们给出了328道React的面试题,由我整理好发给大家,同时发布在了前端面试每日3+1的React专题,希望对大家有所帮助,同时大...

    kumfo 评论0 收藏0
  • redux-saga实现与原理

    摘要:特点集中处理副作用问题异步实现为监听执行的工作形式主要是借鉴模式和使用进行实现的。返回的遍历器对象,可以依次遍历函数内部的每一个状态。为了方便,下文中是的简称。若任务仍在运行中则为任务抛出的错误。由于循环,再次执行。 介绍redux-saga使用和常用api介绍的文章很多,但是真正介绍原理的却很少,下面我用自己的思路讲一下redux-saga的执行过程。源码有很多删减,感兴趣的可自行查...

    itvincent 评论0 收藏0
  • 浅谈Redux(之一):Middleware原理

    摘要:作为目前最火的模式实现之一,它有很多的点值得研究。这个函数既然要用于,也就是说它接收一个形式为的函数,对其一层层嵌套形式为。这个会在开始时发起一个,并在这个时发起另一个成功或失败的。为了方便起见,会返回这个让调用者可以等待。 Redux作为目前最火的Flux模式实现之一,它有很多的点值得研究。今天我们首先来看看它的Middleware。 熟悉Express或者koa的朋友对Middle...

    cocopeak 评论0 收藏0

发表评论

0条评论

jollywing

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<