资讯专栏INFORMATION COLUMN

redux源码解读--applyMiddleware源码解析

Atom / 508人阅读

摘要:的中间件主要是通过模块实现的。返回的也是一个对象这个其实就是,各个中间件的最底层第三层的哪个函数组成的圆环函数构成的这就是对源码的一个整体解读,水平有限,欢迎拍砖。后续的源码解读和测试例子可以关注源码解读仓库

applyMiddleware源码解析

中间件机制redux中是强大且便捷的,利用redux的中间件我们能够实现日志记录,异步调用等多种十分实用的功能。redux的中间件主要是通过applyMiddleware模块实现的。下面,我们就好好的看一下,这个模块到底有什么神奇的魔力。

关于中间件的使用,不了解的同学还需要参考redux文档进行学习。

在我们进行中间件源码剖析之前,我们需要知道一件事:中间件模块在redux的源码中是怎么被被调用的?只有明白了这个问题,我们才能够知道各个参数分别代表的是什么含义。

中间件的本质是作为enhancer而存在的。所以,它是通过createStore方法传递到redux的内部中的。在[createStore源码分析]()中有这样一段代码:

if (typeof enhancer !== "undefined") {
    if (typeof enhancer !== "function") {
        throw new Error("Expected the enhancer to be a function.")
    }

    return enhancer(createStore)(reducer, preloadedState)
}

从这段代码中,我们不难看出,中间件模块是一个高阶函数。其函数签名可以表述如下:

const applyMiddleware = (各个中间件列表) => (createStore(创建store)) => (reducer(reducer集合), preloadedState(初始state)) => {}

明白了上面的那个问题,还有一个问题是我们需要知道的--就是redux的中间件的形式是怎么样的?这里,我们选择了用于处理异步的中间件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;

而在redux中我们应该怎么使用它?

createStore(reducers, applyMiddleware(thunk))

到这里,我们知道了redux是怎么使用中间件的。下面,我们就要详细的解释:redux的源码内部是怎么处理中间件的。为了帮助大家更好的理解,先给大家扯点东西。redux的中间件都是遵循一定规范的。不管是官方的中间件还是我们以后需要自己写的中间件,其函数签名都是一定的。也就是说,中间件的基本的格式都是一样的,接收的参数也是redux注入进去的。下面就是redux中间件的基本格式:

const reduxMiddleware = ({dispatch, getState}[简化的store]) => (next[上一个中间件的dispatch方法]) => (action[实际派发的action对象]) => {}

到这里,我们就可以去深究redux中间件的源码了:

export default function applyMiddleware(...middlewares) {
  // middlewares就是我们传递给applyMiddlewarez函数的一系列中间件函数
  return (createStore) => (...args) => {
    // createStore就是redux用于创建store的方法,args === [reducers, preloadedState]。下面这句话就是在中间件的内部,使用我们传递的参数创建一个store对象
    // 注:这一块没有传递enhancer,所以返回的就是我们经常使用的store对象
    const store = createStore(...args)
    // 获取store对象的dispatch方法
    let dispatch = store.dispatch
    // 保存的是中间件函数的第二层函数
    let chain = []

    // 传递给中间件的第一层的函数的参数,
    const middlewareAPI = {
      getState: store.getState,
      // 重写了dispatch方法,其实就是store.dispatch(...args)
      dispatch: (...args) => dispatch(...args)
    }

    /** 
     * 着重给大家详细的解释一下这一块
     * 假设我们给applyMiddleware函数传递的中间件是
     * applyMiddleware(
     *      f1 => g1 => h1(...arg) => {},
     *      f2 => g2 => h2(...arg) => {}
     * )
     * 运行下面的这行代码之后,chain中保存的内容是
     * chain = [g1 => h1(...arg) => {}, g2 => h2(...arg) => {}]
     */
    
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    /**
     * 当我们把chain传入到 compose中后,根据我们对compose的分析,
     * compose(...chain)(store.dispatch)的结果就是:
     * g1(h2(...arg)) => h1(...arg)
     * 
     * 也就是说,按照上面的这个形式,下面的dispatch和h1函数是一样的,所以,h1的参数,就是我们需要派发的action,当我们调用dispatch的时候,其实就相当于调用h1(action),而在h1的内部,这个action是由g1的参数
     * 也就是h2进行派发的,所以这个时候action就传递到了h2的内部,而h2的参数是由g2的参数,也就是实际传入的store.dispatch进行派发的,就这样层层传入,层层输出,就形成了我们强大的中间件机制。
     */
    dispatch = compose(...chain)(store.dispatch)

    // 返回的也是一个store对象
    return {
      ...store,
      // 这个dispatch其实就是,各个中间件的最底层(第三层)的哪个函数组成的圆环函数构成的
      dispatch
    }
  }
}

这就是对applyMiddleware源码的一个整体解读,水平有限,欢迎拍砖。后续的源码解读和测试例子可以关注:redux源码解读仓库

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

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

相关文章

  • redux源码解读--createStore源码解析

    摘要:源码解析是最核心的模块。比如,当我们需要使用中间件的时候,就会像第三个参数传递一个返回值是一个。后续的源码解读和测试例子可以关注源码解读仓库 createStore源码解析 createStore是redux最核心的模块。这个模块就是用于创建一个store对象,同时,对外暴露出dispatch,getState,subscribe和replaceReducer方法。(源码中关于obse...

    tianren124 评论0 收藏0
  • Redux 入坑进阶 - 源码解析

    摘要:否则的话,认为只是一个普通的,将通过也就是进一步分发。在本组件内的应用传递给子组件源码解析期待一个作为传入,里面是如果只是传入一个,则通过返回被绑定到的函数遍历并通过分发绑定至将其声明为的属性之一接收的作为传入。 原文链接:https://github.com/ecmadao/Co...转载请注明出处 本文不涉及redux的使用方法,因此可能更适合使用过redux的玩家翻阅? 预热...

    BothEyes1993 评论0 收藏0
  • redux源码阅读--主模块

    摘要:主模块的入口模块就是。主要就做两件事引入个功能模块,并挂载至同一个对象上,对外暴露。在非环境下压缩代码,给予警告。后续的源码解读和测试例子可以关注源码解读仓库 主模块 redux的入口模块就是src/index.js。这个文件的代码十分简单。主要就做两件事: 引入个功能模块,并挂载至同一个对象上,对外暴露。 在非production环境下压缩代码,给予警告。 下面是模块的源码(只包...

    testHs 评论0 收藏0
  • 不一样的redux源码解读

    摘要:这里还有一个疑问点就是的嵌套,最开始也我不明白,看了源码才知道,这里返回的也是接受也就是一个所以可以正常嵌套。以作为参数,调用上一步返回的函数以为参数进行调用。 1、本文不涉及redux的使用方法,因此可能更适合使用过 redux 的同学阅读2、当前redux版本为4.0.13、更多系列文章请看 Redux作为大型React应用状态管理最常用的工具。虽然在平时的工作中很多次的用到了它...

    Salamander 评论0 收藏0
  • 重读redux源码(二)

    摘要:函数组合,科里化的串联结合示例源码,实现也很优雅,对于返回的,将等参数传递进去,然后执行,等待回调异步完成再。对于正常对象则进行下一步。前言 作为前端状态管理器,这个比较跨时代的工具库redux有很多实现和思想值得我们思考。在深入源码之前,我们可以相关注下一些常见问题,这样带着问题去看实现,也能更加清晰的了解。 常见问题 大概看了下主要有这么几个: redux三大原则 这个可以直接参考...

    dingda 评论0 收藏0

发表评论

0条评论

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