资讯专栏INFORMATION COLUMN

【源码解析】redux-thunk

simpleapples / 2207人阅读

摘要:的返回值是函数,这个函数经调用,传入参数,之后会在中间件链上进行传递,只要保证每个中间件的参数是并且将传递给下一个中间件。

了解了Redux原理之后,我很好奇Redux中间件是怎么运作的,于是选了最常用的redux-thunk进行源码分析。

此次分析用的redux-thunk源码版本是2.2.0,redux源码版本是3.7.2。并且需要了解Redux原理

redux中间件都是由redux的applyMiddleware()方法所挂载的

export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    const store = createStore(reducer, preloadedState, enhancer)
    let dispatch = store.dispatch
    let chain = []

    //暴露给中间件的API,所以redux-thunk可以使用形如return (dispatch, getState)=>{}
    const middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
    //将暴露的API给中间件,调用中间件函数,生成中间件返回值函数(为什么返回值是函数?不是函数下面的compose()就报错了)
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    //组合全部中间件的返回值函数, chain是中间件返回值函数们
    //然后reduce起来的函数返回的也是函数,将store原来的dispatch传进去,dispatch函数也是接受一个action并返回一个action,作为中间件链的头部
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

可以看到redux主要做了以下事情:

对中间件们使用map,将dispatchgetState传递进去

使用compose将中间件组合起来,最后传入原生的store.dispatch

compose函数则是简单的将中间件进行串联调用

//compose(funcA, funcB, funcC) 等于 (args)=>funcA(funcB(funcC(args)))
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)))
}

最后我们回到redux-thunk

redux-thunk的代码很短,只有短短14行

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;

它对外暴露的是const thunk = createThunkMiddleware();,也就是({dispatch, getState})=>{...}这个函数。

然后经chain = middlewares.map(middleware => middleware(middlewareAPI))传入dispatchgetStatechain里面是next=>{...},进行compose

compose(a,b,c)的返回值是函数(...args)=>a(b(c(...args))),这个函数经调用,传入参数store.dispatch,之后action会在中间件链上进行传递,只要保证每个中间件的参数是action并且将action传递给下一个中间件。

具体到redux-thunk中,它先检查action是否是函数,一般的action都是plain object,如果是函数就应该是由thunk处理。如果不是,传递给nextnext就是下一个中间件。

如果是函数,则调用这个函数并将dispatch, getState, extraArgument传入。这也就是为什么我们需要将thunk action生成函数(注意action和action生成函数的区别)写成() => (dispatch, getState) => {...},传入redux-thunk的action就是(dispatch, getState)=>{...}这个函数

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

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

相关文章

  • 浅析`redux-thunk`中间件源码

    摘要:大多的初学者都会使用中间件来处理异步请求,其理解简单使用方便具体使用可参考官方文档。源码的源码非常简洁,出去空格一共只有行,这行中如果不算上则只有行。官方文档中的一节讲解的非常好,也确实帮我理解了中间件的工作原理,非常推荐阅读。 总觉得文章也应该是有生命力的,欢迎关注我的Github上的博客,这里的文章会依据我本人的见识,逐步更新。 大多redux的初学者都会使用redux-thunk...

    wing324 评论0 收藏0
  • 简单梳理Redux的源码与运行机制

    摘要:然后循环调用中的更新函数,更新函数一般是我们的渲染函数,函数内部会调用来获取数据,所以页面会更新。前言 前几天写了一篇react另一个状态管理工具Unstated的源码解析。 开启了我的看源码之路。想一想用了好长时间的redux,但从没有深究过原理,遇到报错更是懵逼,所以就啃了一遍它的源码,写了这篇文章, 分享我对于它的理解。 API概览 看一下redux源码的index.js,看到了我们最...

    刘东 评论0 收藏0
  • 简单梳理Redux的源码与运行机制

    摘要:然后循环调用中的更新函数,更新函数一般是我们的渲染函数,函数内部会调用来获取数据,所以页面会更新。 欢迎访问个人网站:https://www.neroht.com/ 前言 前几天写了一篇react另一个状态管理工具Unstated的源码解析。开启了我的看源码之路。想一想用了好长时间的redux,但从没有深究过原理,遇到报错更是懵逼,所以就啃了一遍它的源码,写了这篇文章,分享我对于它的理...

    betacat 评论0 收藏0
  • redux 核心源码解析

    摘要:核心源码解析本文默认,你已经有了一定的基础。定义如何更新初始状态是让中间件按照规定模型洋葱模型回形针模型执行的函数,就是下文将会介绍的函数的返回值返回中的。洋葱模型回形针模型调用后的结果对上面的代码换一种展现方式中间件要执行,先得执行。 redux 核心源码解析 本文默认,你已经有了一定的es6基础。源码有删减,对其中的核心逻辑做解释 redux 是 一个用 javascript 管...

    cgh1999520 评论0 收藏0
  • redux中间件探秘

    摘要:接下来我们来看看源码中的模块是怎么应用中间件的。如何实现中间件操作的。新的会从第一个中间件开始触发,这样,在我们调用的时候,就会将中间件走一遍了。函数如果存在多个中间件,直接使用方法将各个中间件嵌套起来。 从redux-thunk引出思考 在使用redux-thunk进行异步action书写的时候,我经常好奇redux到底如何运作,让asyncAction成为可能 为了探究,我们必须看...

    Jeff 评论0 收藏0

发表评论

0条评论

simpleapples

|高级讲师

TA的文章

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