记一次修改框架源码的经历,修改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 ...
随机推荐
- EasySwoole-ElasticSearch-Head启动
- linux下更改文件字符格式为uft-8
liunx下发布的.net Core 程序,发现短信签名不错误不能发出.后来检查发现配配文件中的字符为乱码才知道是因为字符格式问题. 因为服务器批较多,还是使用命令来解决比较快.使用iconv来更改. ...
- LGP6442题解
和SP13106是双倍经验哦 我们首先发现 \(m=20\),所以一言不合先状压. 然后发现状压了之后我们实际上要求的是有多少个子集按位或的值为全集,相当于求有多少个子集按位与的值为 \(0\).(把 ...
- LGP2522题解
双倍经验题. 柯以看成是P3455的扩展. 首先这个范围内是数我们柯以用类似二维前缀和的思想,看成: \(ans(a,b,c,d)=ans(1,b,1,d)+ans(1,a-1,1,c-1)-ans( ...
- 使用ntp 实现时间同步
1.首先安装NTP [root@localhost /]# yum install ntp -y2.查看是否安装成功 rpm -qa|grep ntp [root@hadoop102 桌面]# vi ...
- 采用二进制文件方式安装loki和promtail
1. 下载二进制文件 官方下载地址:https://github.com/grafana/loki/releases 下载如图所示的这俩文件,Grafana采用yum方式安装 cd /usr/loca ...
- python 实现批量md转word
# qianxiao996精心制作 #博客地址:https://blog.csdn.net/qq_36374896 #md批量转word import os def auto_md_to_docx(f ...
- 14FPGA综设之图像边沿检测的sobel算法
连续学习FPGA基础课程接近一个月了,迎来第一个有难度的综合设计,图像的边沿检测算法sobel,用verilog代码实现算法功能. 一设计功能 (一设计要求) (二系统框图) 根据上面的系统,Veri ...
- bzoj3879 SvT(后缀自动机+虚树)
bzoj3879 SvT(后缀自动机+虚树) bzoj 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始位置 ...
- 洛谷P1049 [NOIP2001 普及组] 装箱问题
本题就是一个简单的01背包问题 1.因为每个物品只能选一次,而且要使箱子的剩余空间为最小.所以可以确定属性为 MAX 2.由于是从n个物品里面选i个物品 那么就是选出的i个物品的空间总和要尽可能的 ...