假设存在A/B函数相互关联,A函数每次一次正向操做,B函数必然会执行一次反向操做,A/B函数保证相关抵消。 那么考虑如下场景:git
ABABABABABABABABABABABABABgithub
A/B函数高频率触发,可是最终效果都是抵消的,此时若是基于用户交互优化,以及节约性能的考虑,能够进行约束节流。 不改变最终的效果,可是能够减小触发次数。数据库
优化效果可能以下:npm
A----------B----------A------------Bapp
遇到这种问题,机智的我尝试写了个函数,实现了大体效果,源码地址:BT异步
上图中所示,若是不作优化,基本上每一行都会执行真正的A/B函数逻辑(以/SKIP/、/DONE/标记开头的那些,/SHOW/是为了展现那个时间点的数据库结果)。函数
图中示例是以300ms进行约束节流的,优化后,图中白色和红色那些行即为真正执行的A/B函数逻辑性能
经过计数器来记录A/B函数执行次数,同时利用时间戳和定时器,判断A函数执行后,在节流时间内将多余的A函数略过,同时最大控制B函数在节流时间的末尾执行。优化
count: 0, // 平衡值,最终全部A/B函数执行完后,确保count === 0
ctime: 0, // 每次执行真的A函数开始后的触发时间
F_callTimes: 0, // A函数(不管真假)执行次数
B_callTimes: 0, // B函数(不管真假)执行次数
复制代码
为了确保不出错,在定时器里经过判断A/B函数执行次数,始终确保两个函数执行次数相一致。ui
timeRef.unset().set(() => {
const delta = F_callTimes - B_callTimes;
for (let i = 0; i <= delta; i++) {
wrapperB(...args); // 执行B包裹函数
}
}, idleness);
复制代码
有同窗看到了不管真假,确定满脸问号。
是这样的,真的A/B函数就是真的业务逻辑,可能会带有各类反作用,消耗性能等。而假的A/B函数,就是替换真的A/B函数而存在的,能够用来打印日志等等。
在开发这个BT过程当中,遇到了一个问题,若是A/B函数,传参不一样的话,那么很明显是用来执行不一样操做的,此时须要进行分类约束节流。这个简单能够经过一个对象记录分类。
function generateRecord(type) {
BTRecrod[type] = {
count: 0,
ctime: 0,
F_callTimes: 0,
B_callTimes: 0,
timeRef: Object.assign({}, timeout)
};
}
复制代码
而type就是分类的依据,那怎么生成呢?经过参数拼接一下,就获得不一样的type。这里简单只作了原始值类型的处理,若是是对象的话,能够深度遍历一下去计算生成不同的type~
export function generateType(...args) {
return ["BT"].concat(args).join("_");
}
复制代码
至此,还有一个问题没有处理,若是A/B函数是异步的怎么办?可能须要等待A/B函数异步返回成功的时候,才能算作执行成功...
最终调用效果以下:
import { BT } from "binary-throttle";
function forward() {
// @TODO
}
function backward() {
// @TODO
}
const [X, Y] = BT(forward, backward, {
// idleness: 300,
// fallbackF: () => console.log('X was ignore this time.'),
// fallbackB: () => console.log('Y was ignore this time.')
});
复制代码
接下来不管forward,backward函数交换调用多么频繁,通过BT的约束节流处理后,都只会大大减小调用次数,可是最终结果仍是一致的。
这个函数我已经发了个包名叫binary-throttle
,仍是不推荐你们使用(由于),写出来纯粹是交个朋友😏,给你们提供点思路,顺便本身也记录一下~
这种场景可能比较少见,不过不影响你们感兴趣能够戳戳: BT
(若是有同窗好奇去搜,颇有可能双函数约束节流这个名词就是不存在,我瞎编的哈哈哈哈...)