博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
redux middleware 源码分析
阅读量:4960 次
发布时间:2019-06-12

本文共 3137 字,大约阅读时间需要 10 分钟。

161dd3870015d2a9?w=640&h=280&f=jpeg&s=12875

middleware 的由来

在业务中需要打印每一个 action 信息来调试,又或者希望 dispatch 或 reducer 拥有异步请求的功能。面对这些场景时,一个个修改 dispatch 或 reducer 代码有些乏力,我们需要一个可组合的、自由增减的插件机制,Redux 借鉴了 Koa 中 middleware 的思想,利用它我们可以在前端应用中便捷地实现如日志打印、异步请求等功能。

161dd387003424f6?w=718&h=200&f=jpeg&s=14678

比如在中,进行了如下调用后,redux 就集成了 thunk 函数调用以及打印日志的功能。

import thunk from 'redux-thunk'import logger from '../middleware/logger'const enhancer = applyMiddleware(thunk, logger),  // 以 redux-thunk、logger 中间件为例介绍中间件的使用const store = createStore(rootReducer, enhancer)

下面追本溯源,来分析下源码。

applyMiddleware 调用入口

export default function createStore(reducer, preloadedState, enhancer) {  // 通过下面代码可以发现,如果 createStore 传入 2 个参数,第二个参数相当于就是 enhancer  if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {    enhancer = preloadedState    preloadedState = undefined  }  if (typeof enhancer !== 'undefined') {    return enhancer(createStore)(reducer, preloadedState)  }  ...}

由上述 发现,applyMiddleware 会进行 applyMiddleware(thunk, logger)(createStore)(reducer, preloadedState) 的调用。

如下

export default function applyMiddleware(...middlewares) {  return createStore => (...args) => {    const store = createStore(...args)    let dispatch = store.dispatch    let chain = []    const middlewareAPI = {      getState: store.getState,                // 调用 redux 原生方法,获取状态      dispatch: (...args) => dispatch(...args) // 调用 redux 原生 dispatch 方法    }    // 串行 middleware    chain = middlewares.map(middleware => middleware(middlewareAPI))    dispatch = compose(...chain)(store.dispatch)    return {      ...store,      dispatch // 返回加工过的 dispatch    }  }}

可以发现 applyMiddleware 的作用其实就是返回加工过的 dispatch,下面会着重分析 middlewares 是如何串行起来的以及 dispatch 是如何被加工的。

串行 middleware

const middlewareAPI = {  getState: store.getState,  dispatch: (...args) => dispatch(...args)}chain = middlewares.map(middleware => middleware(middlewareAPI))dispatch = compose(...chain)(store.dispatch)

观察上述代码后发现每个 middleware 都会传入参数 middlewareAPI,来看下中间件 以及 , 发现中间件接受的第一个参数正是 ({ dispatch, getState })

// logger 源码export default ({ dispatch, getState }) => next => action => {  console.log(action)  return next(action) // 经 compose 源码分析,此处 next 为 Store.dispatch}
// redux-thunk 源码export default ({ dispatch, getState }) => next => action => {  if (typeof action === 'function') {    return action(dispatch)  }  return next(action) // 此处 next 为 logger 中间件返回的 (action) => {} 函数}

dispatch 是如何被加工的

接着上个小节,在 dispatch = compose(...chain)(store.dispatch) 中发现了 compose 函数,来看下

export default function compose(...funcs) {  // ...  return funcs.reduce((a, b) => (...args) => a(b(...args)))}

compose 源码中的 funcs.reduce((a, b) => (...args) => a(b(...args))) 算是比较重要的一句,它的作用是返回组合参数后的函数,比如 compose(f, g, h) 等价于 (...args) => f(g(h(...args))),效果图如下所示,调用 this.props.dispatch() 后,会调用相应的中间件,最终会调用 redux 原生的 store.dispatch(),并且可以看到中间件调用的形式类似数据结构中的栈(先进后出)。

161dd3870009f6b7?w=360&h=300&f=jpeg&s=15622

拿上个小节提到的 logger、redux-thunk 中间件为例,其 middleware 的内部串行调用方式如下,从而完成了 dispatch 功能的增强(支持如 this.props.dispatch(func) 的调用以及日志功能)。具体可以看

action => {  if (typeof action === 'function') {    return action(dispatch)  }  return (action => {    console.log(action)    return store.dispatch(action)  })(action)}

参考文献

深入React技术栈

转载于:https://www.cnblogs.com/MuYunyun/p/8486533.html

你可能感兴趣的文章
HOT SUMMER 每天都是不一样,积极的去感受生活 C#关闭IE相应的窗口 .
查看>>
windows平台上编译mongdb-cxx-driver
查看>>
optionMenu-普通菜单使用
查看>>
MVC3分页传2参
查看>>
2016-2017-2点集拓扑作业[本科生上课时]讲解视频
查看>>
appium(13)- server config
查看>>
IIS负载均衡-Application Request Route详解第六篇:使用失败请求跟踪规则来诊断ARR...
查看>>
管理信息系统 第三部分 作业
查看>>
[Leetcode Week13]Search a 2D Matrix
查看>>
查看端口占用cmd命令
查看>>
2019.01.17王苛震作业
查看>>
Halcon学习(八)文本操作
查看>>
MFC电子词典
查看>>
简单工厂(Simple Factory)
查看>>
04: 打开tornado源码剖析处理过程
查看>>
02: 安装epel 解决centos7无法使用yum安装nginx
查看>>
清除浮动
查看>>
PayPal(贝宝)支付接口、文档、IPN
查看>>
站立会议总结07
查看>>
ORACLE 10G R2_执行计划中cost cardinality bytes cpu_cost io_cost解释
查看>>