redux是一个数据状态管理的js框架,redux把行为抽象成一个对象,把状态抽象成一个很大的数据结构,每次用户或者其他什么方式需要改变页面都可以理解成对数据状态的改变,根据出发这次改变的不同从而有各式各样的action(行为),如何根据action(行为)来改变状态呢?这时候就需要一个reduce,reduce必须是一个纯函数,reduce是一个定义行为如何改变状态的逻辑处理的函数,action传入通过reduce的逻辑改变状态,最后状态发生改变,发出订阅消息,触发监听函数的执行。思路很简单,看文档也很容易上手,代码量也不大。

但是最近使用redux发现一个问题,如果同时触发多个action的话,会频繁触发监听函数的执行,比如如下代码

(function(){
dispatch(action1);
dispatch(action2)
})(dispatch)

  会触发2次监听函数,一般监听函数回去修改视图,但其实处理完这两次action,在去触发监听函数,用户看到的效果是一样的,不会看到触发第一次action和第二次action之间的过渡,但是如果能一次性把状态跟新完,在触发一次监听函数,那样的话会避免执行一些没必要的代码,例如代码如下:

(function(){
dispatch(action1,action2); })(dispatch)

  但是阅读了redux源码发现,dispatch函数只能接受一个参数,源码如下:

function dispatch(action) {
if (!isPlainObject(action)) {
throw new Error(
'Actions must be plain objects. ' +
'Use custom middleware for async actions.'
)
} if (typeof action.type === 'undefined') {
throw new Error(
'Actions may not have an undefined "type" property. ' +
'Have you misspelled a constant?'
)
} if (isDispatching) {
throw new Error('Reducers may not dispatch actions.')
} try {
isDispatching = true
currentState = currentReducer(currentState, action)
} finally {
isDispatching = false
} const listeners = (currentListeners = nextListeners)
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
} return action
}

  当然了如果修改源码的会有很多种思路,第一种就是监听还是放到事件队列的尾部执行,如下代码:

var nextTick=(function(){
let promise = new Promise(function (resolve,rej){
resolve()
})
return function (fn){
promise.then(fn)
}
})() nextTick(listen)

  这样方式的话,也许会出现队列非常多的话会延迟跟新试图,对用户不友好,最后我采用了最后一个办法,让dispatch函数可以一次处理多个action:

function dispatch(...actions) {

    if (actions.some((action, index, arr) => {
return !isPlainObject(action)
})) {
throw new Error(
'Actions must be plain objects. ' +
'Use custom middleware for async actions.'
)
} // if (!isPlainObject(action)) {
// throw new Error(
// 'Actions must be plain objects. ' +
// 'Use custom middleware for async actions.'
// )
// }
if (actions.some((action, index, arr) => {
return typeof action.type === 'undefined'
})) {
throw new Error(
'Actions must be plain objects. ' +
'Use custom middleware for async actions.'
)
} // if (typeof action.type === 'undefined') {
// throw new Error(
// 'Actions may not have an undefined "type" property. ' +
// 'Have you misspelled a constant?'
// )
// } if (isDispatching) {
throw new Error('Reducers may not dispatch actions.')
} try {
isDispatching = true
currentState = actions.reduce(currentReducer, currentState)
// currentState = currentReducer(currentState, action)
} finally {
isDispatching = false
} const listeners = (currentListeners = nextListeners)
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
} return actions
}

  

记一次修改框架源码的经历,修改redux使得redux 可以一次处理多个action,并且只发出一次订阅消息的更多相关文章

  1. ABP框架源码学习之修改默认数据库表前缀或表名称

    ABP框架源码学习之修改默认数据库表前缀或表名称 1,源码 namespace Abp.Zero.EntityFramework { /// <summary> /// Extension ...

  2. 修改elementUI源码新增组件/修改组件

    前言 经常我们会遇到elementUI组件库期间有5%达不到我们想要的需求,第一我们重新写组件,第二我们改源码 安装element https://github.com/ElemeFE/element ...

  3. YII框架源码分析(百度PHP大牛创作-原版-无广告无水印)

           YII 框架源码分析    百度联盟事业部——黄银锋 目 录 1. 引言 3 1.1.Yii 简介 3 1.2.本文内容与结构 3 2.组件化与模块化 4 2.1.框架加载和运行流程 4 ...

  4. TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端)、UDP客户端

    目录 说明 TCP/UDP通信主要结构 管理多个Socket的解决方案 框架中TCP部分的使用 框架中UDP部分的使用 框架源码结构 补充说明 源码地址 说明 之前有好几篇博客在讲TCP/UDP通信方 ...

  5. CI框架源码阅读笔记3 全局函数Common.php

    从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...

  6. CI框架源码阅读笔记2 一切的入口 index.php

    上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里再次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中, ...

  7. Android Small插件化框架源码分析

    Android Small插件化框架源码分析 目录 概述 Small如何使用 插件加载流程 待改进的地方 一.概述 Small是一个写得非常简洁的插件化框架,工程源码位置:https://github ...

  8. iOS学习——布局利器Masonry框架源码深度剖析

    iOS开发过程中很大一部分内容就是界面布局和跳转,iOS的布局方式也经历了 显式坐标定位方式 --> autoresizingMask --> iOS 6.0推出的自动布局(Auto La ...

  9. 【java集合框架源码剖析系列】java源码剖析之ArrayList

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 本博客将从源码角度带领大家学习关于ArrayList的知识. 一ArrayList类的定义: public class Arr ...

随机推荐

  1. 如何在 MWeb 中配置 Hexo 等静态网站

    原文链接 参考链接: https://zh.mweb.im/mweb-1.4-add-floder-octpress-support.html https://zhuanlan.zhihu.com/p ...

  2. 使用vscode Container开发调试envoy

    由于我最近在研究 envoy 这个项目,这是个cpp的项目,对于我这种cpp新人来说还是比较有压力的,感觉处处都是坑,开个引导文章记录一下. 如果要研究 envoy 项目源码,那肯定是需要代码跳转的, ...

  3. vue3-组件中使用setup函数获取vuex中的数据的新方式

    传统方式 setup() { const store = useStore() //传统方式 const aName = computed(() => store.state.name) ret ...

  4. mysql 索引模板

    DROP TABLE IF EXISTS `table_name`; CREATE TABLE `table_name` ( `id` bigint(20) UNSIGNED NOT NULL AUT ...

  5. Rsync未授权访问

    1.漏洞名称 Rsync 未授权访问漏洞 2.漏洞原理 rsync是Linux下一款数据备份工具,支持通过rsync协议.ssh协议进行远程文件传输. 其中rsync协议默认监听873端口,如果目标开 ...

  6. AOP详解之三-创建AOP代理后记,创建AOP代理

    AOP详解之三-创建AOP代理后记,创建AOP代理. 上篇文章已经获取到了AOP的信息,接下来就是拿着这些AOP的信息去创建代理了. 首先我们看下创建AOP代理的入口处. //这个方法将返回代理类 p ...

  7. 2022IDEA配置启动lilishop的swagger展示

    目录 一.概述 二.基本构建 三.Git 导入编译器 四.模块描述浅析 五.配置文档 1.注释配置文件 2.添加配置 3.暂时关闭权限 4.浏览器测试访问 5.其他需要修改模块 六.参考文献 结语 一 ...

  8. (转载)linux下Yum的$releasever和$basearch的取值

    https://blog.csdn.net/whatday/article/details/51097456

  9. Java中如何强制类型转换

    例如,当程序中需要将 double 型变量的值赋给一个 int 型变量,该如何实现呢? 显然,这种转换是不会自动进行的!因为 int 型的存储范围比 double 型的小.此时就需要通过强制类型转换来 ...

  10. 数据分析之Numpy的基本操作

    Numpy NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库. 1 创建 ndarray 使 ...