记一次修改框架源码的经历,修改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 ...
随机推荐
- CF1601C题解
赛时一小时,赛后十分钟. 题意:给定一个序列 \(a\) 和一个集合 \(b\),问将 \(b\) 中所有元素插入 \(a\) 后逆序对最少是多少. 观察样例解释,发现 \(b\) 已经被排序过了,于 ...
- U8g2库的使用
一.硬件介绍: 由于笔者这里只有0.96寸的OLED屏幕,那就讲讲最常用的0.96寸OLED屏幕吧. OLED介绍: OLED,即有机发光二极管( Organic Light Emitting Dio ...
- mysql数据库-8.0安装及环境搭建
1.MySQL8.0 For Windows zip包下载地址 https://dev.mysql.com/downloads/file/?id=476233,进入页面后点击底部&quo ...
- RESTful API设计规范总结
RESTful 是目前最流行的 API 设计规范,用于 Web 数据接口的设计. 它的大原则容易把握,但是细节不容易做对.本文总结 RESTful 的设计细节,介绍如何设计出易于理解和使用的 API. ...
- [SPDK/NVMe存储技术分析]001 - SPDK/NVMe概述
1. NVMe概述 NVMe是一个针对基于PCIe的固态硬盘的高性能的.可扩展的主机控制器接口. NVMe的显著特征是提供多个队列来处理I/O命令.单个NVMe设备支持多达64K个I/O 队列,每个I ...
- EasyUI 之datagrid 使用 【DataGrid属性解释】
可选的参数 DataGrid 属性 覆写了 $.fn.datagrid.defaults. 参数名 类型 描述 默认值 title string Datagrid面板的标题 null iconCls ...
- 如何运行MATLAB和C++混合编程
在GitHub下载了一个大佬的滤波器程序,包含MATLAB和C++,刚开始直接运行,发现提示如下: 然后,第一步:点击截图访问后面的链接,跳转到如下截图: 第二步:点击上面截图的左下角,R2015b版 ...
- Basler acA1300-200uc相机使用教程
https://www.baslerweb.com/cn/products/cameras/area-scan-cameras/ace/aca1300-200uc/ 开发文档 https://zh.d ...
- luoguP6623 [省选联考 2020 A 卷] 树(trie树)
luoguP6623 [省选联考 2020 A 卷] 树(trie树) Luogu 题外话: ...想不出来啥好说的了. 我认识的人基本都切这道题了. 就我只会10分暴力. 我是傻逼. 题解时间 先不 ...
- 论文翻译:2021_Acoustic Echo Cancellation with Cross-Domain Learning
论文地址:https://graz.pure.elsevier.com/en/publications/acoustic-echo-cancellation-with-cross-domain-lea ...