双函数约束节流的设计

背景

假设存在A/B函数相互关联,A函数每次一次正向操做,B函数必然会执行一次反向操做,A/B函数保证相关抵消。 那么考虑如下场景:git

ABABABABABABABABABABABABABgithub

目标

A/B函数高频率触发,可是最终效果都是抵消的,此时若是基于用户交互优化,以及节约性能的考虑,能够进行约束节流。 不改变最终的效果,可是能够减小触发次数。数据库

优化效果可能以下:npm

A----------B----------A------------Bapp

遇到这种问题,机智的我尝试写了个函数,实现了大体效果,源码地址:BT异步

database

上图中所示,若是不作优化,基本上每一行都会执行真正的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

(若是有同窗好奇去搜,颇有可能双函数约束节流这个名词就是不存在,我瞎编的哈哈哈哈...)

相关文章
相关标签/搜索