applyMiddleware源码中的闭包
闭包都是个老掉牙的话题了,这次又提起,是因为重看Redux源码时发现了applyMiddleware里的用法很巧妙。我们先看一个简单的例子。
var a = (num) => num + 1
var b = {
name: (num) => a(num)
} a = (num) => num + 5 console.log(b.name(3))
打印结果是4还是8呢?
对象b有一个属性name。name是一个方法,函数体里使用了函数a,a是全局作用域的变量,之后a修改了。答案是8。我们不是在作用域里取到变量的值,而是在作用域所对应的执行上下文取到变量的值,并且可能同样的作用域,相同的变量取到的值是不同的。 可以看看这篇文章系列。
接下来看我们的applyMiddleware源码。
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
}
}
}
一个比较关键的的地方是变量middlewareAPI ,它是一个对象,对象有方法dispatch,该方法内部调用了外部的dispatch。接下来在数组map方法里,该对象作为实参传递。
我们看thunk中间件源码
export default function thunkMiddleware({ dispatch, getState }) {
return next => action =>
typeof action === 'function' ?
action(dispatch, getState) :
next(action);
}
middlewareAPI 传递过来的dispatch一直到判断了action是function的时候才进行传递使用,这个时候的dispatch其实是已经增强的dispatch了,即dispatch = compose(...chain)(store.dispatch)这个dispatch了。
总结起来就是中间件的形参next接受的是原始store.dispatch,而thunkMiddleware({ dispatch, getState })或者说是middleware(middlewareAPI)里的dispatch是增强后的dispatch = compose(...chain)(store.dispatch)这个dispatch了
applyMiddleware源码中的闭包的更多相关文章
- redux:applyMiddleware源码解读
前言: 笔者之前也有一篇关于applyMiddleware的总结.是applyMiddleware的浅析. 现在阅读了一下redux的源码.下面说说我的理解. 概要源码: step 1: apply ...
- Android 源码中的设计模式
最近看了一些android的源码,发现设计模式无处不在啊!感觉有点乱,于是决定要把设计模式好好梳理一下,于是有了这篇文章. 面向对象的六大原则 单一职责原则 所谓职责是指类变化的原因.如果一个类有多于 ...
- jquery源码中noConflict(防止$和jQuery的命名冲突)的实现原理
jquery源码中noConflict(防止$和jQuery的命名冲突)的实现原理 最近在看jquery源码分析的视频教学,希望将视频中学到的知识用博客记录下来,更希望对有同样对jquery源码有困惑 ...
- Python源码中的PyCodeObject
1.Python程序的执行过程 Python解释器(interpreter)在执行任何一个Python程序文件时,首先进行的动作都是先对文件中的Python源代码进行编译,编译的主要结果是产生的一组P ...
- 从express源码中探析其路由机制
引言 在web开发中,一个简化的处理流程就是:客户端发起请求,然后服务端进行处理,最后返回相关数据.不管对于哪种语言哪种框架,除去细节的处理,简化后的模型都是一样的.客户端要发起请求,首先需要一个标识 ...
- Android 网络框架之Retrofit2使用详解及从源码中解析原理
就目前来说Retrofit2使用的已相当的广泛,那么我们先来了解下两个问题: 1 . 什么是Retrofit? Retrofit是针对于Android/Java的.基于okHttp的.一种轻量级且安全 ...
- Eclipse与Android源码中ProGuard工具的使用
由于工作需要,这两天和同事在研究android下面的ProGuard工具的使用,通过查看android官网对该工具的介绍以及网络上其它相关资料,再加上自己的亲手实践,算是有了一个基本了解.下面将自己的 ...
- String源码中的"avoid getfield opcode"
引言: 之前一篇文章梳理了String的不变性原则,还提到了一段源码中注释"avoid getfield opcode",当时通过查阅资料发现,这是为了防止 getfield(获取 ...
- android源码中修改wifi热点默认始终开启
在项目\frameworks\base\wifi\java\android\net\wifi\WifiStateMachine.java里面,有如下的代码,是设置wifi热点保持状态的:如下: pri ...
随机推荐
- C++ 系列:Boost Thread 编程指南
转载自:http://www.cppblog.com/shaker/archive/2011/11/30/33583.html 作者: dozbC++ Boost Thread 编程指南0 前言1 创 ...
- [转]Entity Framework教程(第二版)
源起 很多年前刚毕业那阵写过一篇关于Entity Framework的文章,没发首页却得到100+的推荐.可能是当时Entity Framework刚刚发布介绍EF的文章比较少.一晃这么多年过去了,E ...
- MongDB4.1-入门学习之下载安装配置
下载安装配置三步走 下载,MongoDB官网下载中心 下载_.msi_安装版 安装,注意以下几个步骤: Choose Setup Type: Please Choose Custom Custom S ...
- 【JZOJ3236】矮人排队
description 在七山七海之外的一个小村庄,白雪公主与N个矮人住在一起,所有时间都花在吃和玩League of Legend游戏.白雪公主决心终结这样的生活,所以为他们举办了体育课. 在每节课 ...
- 0817NOIP模拟测试赛后总结
吐槽一句:话说NOIP都取消了还叫NOIP模拟真的好么 于是乎我再次爆炸……(0+20+50=70 rank26) 赛时状态 赛时的状态依旧不佳.不过还是硬逼着自己把三道题都读完,然后开始对出题人静坐 ...
- Webstorm在MAC下的安装方法
一 .注册时,在打开的License Activation窗口中选择“License server”,在输入框输入下面的网址: http://idea.codebeta.cn (新,感谢Rachels ...
- Chrome快捷键, Mac 下 Chrome 浏览器 快捷键
Chrome窗口和标签页快捷键:Ctrl+N 打开新窗口 Ctrl+T 打开新标签页 Ctrl+Shift+N 在隐身模式下打开新窗口 Ctrl+O,然后选择文件 在谷歌浏览器中打开计算机上的文件 按 ...
- Sql Server 中查询存储过程的修改时间
1.按最近修改排序所有存储过程 SELECT [name], [create_date], [modify_date] FROM [sys].[objects] WHERE [type] = 'P' ...
- 让ASPX页面可以提交html标签代码的配置
1:打开web.config文件,在system.web节点里,添加<httpRuntime requestValidationMode="2.0" /> 2:在asp ...
- elasticsearch 中文API 获得(三)
获取API 获取API允许你通过id从索引中获取类型化的JSON文档,如下例: GetResponse response = client.prepareGet("twitter" ...