4、redux源码解析 - 糅合多种dispatch
在开发时,也许需要更多地包装dispatch以实现更加完善的功能。
比如包装 dispatch来打印日志,包装dispatch以支持Promise,各种包装需要密切配合。
之前两篇代码的汇总:
//包装dispatch来打印日志 const addLoggingToDispatch = (store) => { const rawDispatch = store.dispatch; if(!console.group){ return rawDispatch; } return (action) => { console.group(action.type); console.log('%c previous state', 'color: gray', store.getState()); console.log('%c action', 'color: blue', action); const returnValue = rawDispatch(action); console.log('%c previous state', 'color: gray', store.getState()); console.log.group(action.type); return returnValue } } //dispatch支持传入promise对象 const addPromiseSupportToDispatch = (store) => { const rawDispatch = store.dispatch; return (action) => { if(typeof action.then === 'function'){ return action.then(rawDispatch); } return rawDispatch(action); } }
为了使这两种方式同时运作,可以写一个用来初始化sotre的函数,以丰富store.dispatch的功能。
const configureStore = () => { const store = createStore(App); if(process.env.NODE_ENV !== 'production'){ store.dispatch = addLoggingToDispatch(store); } store.dispatch = addPromiseSupportToDispatch(store); return store; }
这样便返回了一个包含有增强型dispatch的store,
仔细研究configureStore函数,我们发现addPromiseSupportToDispatch方法返回了一个符合正常用法的dispatch,
此时它支持dispatch参数是一个promise,它会等待Promise resolve后,利用rawDispatch再次进行action派发。
那么这个rawDispatch是最初、最原始的dispatch吗?在开发环境下,显然不是。因为执行sotre.dispatch = addPromiseSupportToDispatch(store)之前,
已经执行了store.dispatch = addLoggingToDispatch(store)。
换名话说,在执行addPromiseSupportToDispatch时,store.dispatch是上一个包装版本的sotre.dispatch。
明白了这层关系,我们就会想到rawDispatch这个全名不十分准确,它本意是最原始的store.dispatch , 但是在代码执行
时,每一个中间件所获得的store.dispatch都已经被改造,我们将其命名为next。
前面的例子改造之后:
const addLoggingToDispatch = (store) => { const next = store.dispatch; if(!console.group){ return next } return (action) => { //... const resultValue = next(action); //... return resultValue; } } const addPromiseSupportToDispatch = (store) => { const next = store.dispatch; return (action) => { if(typeof action.then === 'function'){ return action.then(next) } return next(action); } }
为了避免上面这样零散地修改公共的api接口,我们可以将这种包装过程收敛 - 声明一个数组,即中间件数组。
它的每一项都是一个中间件,然后统一根据中间件来增强dispatch。
const configureStore = () => { const store = createStore(App); const middleWare = []; if(process.env.NODE_ENV !== 'production'){ middleWare.push(addLoggingToDispatch); } middleWare.push(addPromiseSupportToDispatch); wrapDispatchWithMiddlewares(store, middlewares); return store; } 以上代码中,并不直接执行addLoggingToDispatch和addPromiseToDispatch,而 是将其push到middlewares数组,然后统一执行。这里说的统一执行就是指代码中的wrapDispatchWithMiddleWares(store, middlewares); const wrapDispatchWithMiddlewares = (store, middlewares) => { middlewares.forEach(middleware => { store.dispatch = middleware(store)(store.dispatch); }) }
原文地址:https://www.cnblogs.com/hellolol/p/11379340.html
- [快学Python3]List(列表)
- [快学Python3]Tuple(元组)
- HDU 1248 寒冰王座(完全背包裸题)
- [快学Python3]String(字符串)
- [快学Python3]XML解析处理 - Element Tree
- Educational Codeforces Round 21(A.暴力,B.前缀和,C.贪心)
- [快学Python3]JSON解析
- Codeforces 754A Lesha and array splitting(简单贪心)
- [快学Python3]日期和时间处理
- Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3)(A.B.C,3道暴力题,C可二分求解)
- [快学Python3]目录与文件操作
- Codeforces Round #411 (Div. 2)(A,B,C,D 四水题)
- [快学Python3]INI文件读写
- [快学Python3]迭代器和生成器
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- zookeeper-03 命令行操作
- java连接zookeeper服务器出现“KeeperErrorCode = ConnectionLoss for ...”
- Linux 内存使用率
- CentOS7.4下编译Hadoop-2.7.6
- VMware安装CentOS6
- VMware安装CentOS7 3.1 主机名修改3.2 网卡名修改3.3 ifconfig安装
- VMware网络设置
- Destoon 6.0 guestbook.php 通用SQL注入漏洞
- Hadoop2.7.6_01_部署
- Hadoop2.7.6_02_HDFS常用操作
- Bottle HTTP 头注入漏洞探究
- Hadoop2.7.6_03_HDFS原理
- Hadoop2.7.6_04_HDFS的Shell操作与常见问题
- Hadoop2.7.6_05_mapreduce-Yarn
- Hadoop2.7.6_06_mapreduce参数优化