记一次修改框架源码的经历,修改redux使得redux 可以一次处理多个action,并且只发出一次订阅消息
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,并且只发出一次订阅消息的更多相关文章
- ABP框架源码学习之修改默认数据库表前缀或表名称
ABP框架源码学习之修改默认数据库表前缀或表名称 1,源码 namespace Abp.Zero.EntityFramework { /// <summary> /// Extension ...
- 修改elementUI源码新增组件/修改组件
前言 经常我们会遇到elementUI组件库期间有5%达不到我们想要的需求,第一我们重新写组件,第二我们改源码 安装element https://github.com/ElemeFE/element ...
- YII框架源码分析(百度PHP大牛创作-原版-无广告无水印)
YII 框架源码分析 百度联盟事业部——黄银锋 目 录 1. 引言 3 1.1.Yii 简介 3 1.2.本文内容与结构 3 2.组件化与模块化 4 2.1.框架加载和运行流程 4 ...
- TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端)、UDP客户端
目录 说明 TCP/UDP通信主要结构 管理多个Socket的解决方案 框架中TCP部分的使用 框架中UDP部分的使用 框架源码结构 补充说明 源码地址 说明 之前有好几篇博客在讲TCP/UDP通信方 ...
- CI框架源码阅读笔记3 全局函数Common.php
从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...
- CI框架源码阅读笔记2 一切的入口 index.php
上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里再次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中, ...
- Android Small插件化框架源码分析
Android Small插件化框架源码分析 目录 概述 Small如何使用 插件加载流程 待改进的地方 一.概述 Small是一个写得非常简洁的插件化框架,工程源码位置:https://github ...
- iOS学习——布局利器Masonry框架源码深度剖析
iOS开发过程中很大一部分内容就是界面布局和跳转,iOS的布局方式也经历了 显式坐标定位方式 --> autoresizingMask --> iOS 6.0推出的自动布局(Auto La ...
- 【java集合框架源码剖析系列】java源码剖析之ArrayList
注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 本博客将从源码角度带领大家学习关于ArrayList的知识. 一ArrayList类的定义: public class Arr ...
随机推荐
- 解决github网站打不开的方法
发现github最近经常抽风,之前发现打不开时就挂个梯子,最近梯子也都被封了,尝试了下改host发现效果挺好,方法如下(Mac电脑): 1.通过站长工具找出DNS地址:进入站长工具网站的域名解析网址: ...
- SP3734题解
题意: 有 \(n\) 列表格,第 \(i\) 列有 \(a_i\) 个格子,问在 \(n\) 列表格中有多少种放置 \(k\) 个棋子的方法使没有棋子在同一列和同一行.(如果中间有一个"格 ...
- 网易互娱23届实习笔试_3x3锯齿数独
一.输入: 输入一个3x3数独,字符'.'代表空输入三个宫的域,每个宫包括三个位置,[0,0]表示0行0列 二.输出要求: 1.每个宫里最终123各出现一次, 2.数独中的行列里不出现重复字符: 输出 ...
- SQL基础语法_张三
1.1 建库表语法 1.2 字段数据类型 大致可以分为三类:数值.日期/时间和字符串 (字符)类型. 2. 增删查改 3. 关联查询 4. 子查询
- Hibernate学习笔记(一)-->数据库单表操作
Hibernate框架是一个全ORM映射框架,是一个非常流行的数据库操作框架之一,现在比较流行的还有MyBatis半ORM映射框架 在MyEclipse IDE开发工具中,可以很轻松的搭建Hibern ...
- MySQL — 索引
目录 1.索引概述 2.索引结构 3.索引分类 4.索引语法 5.SQL 性能分析 5.1.执行频次 5.2.慢日志查询 5.3.profile 5.4.explain 6.索引使用规则 6.1.单列 ...
- oracle 中有数据但是sql查询不出来结果(中文)
如 select * from user where name like '%王%': 无数据: 而数据库中确实有姓王的用户. 配置环境变量 NLS_LANG = AMERICAN_AMERICA.A ...
- ASP.NET Core 6框架揭秘实例演示[28]:自定义一个服务器
作为ASP.NET Core请求处理管道的"龙头"的服务器负责监听和接收请求并最终完成对请求的响应.它将原始的请求上下文描述为相应的特性(Feature),并以此将HttpCont ...
- Java基础 - 注解详解
What - 什么是注解? Annontation是Java5开始引入的新特征,中文名称叫注解.它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素( ...
- mysql 在已存在的表中添加/删除字段约束AUTO_INCREMENT遇到的问题
1. 在已存在的表中添加字段约束AUTO_INCREMENT修饰符 mysql> alter table user modify uid int auto_increment primary k ...