debounce throttle 简介
具体的相关概念可以看我之前写的文章。这里我们只简单的介绍
debounce 防抖
在事件被触发n秒后去执行回调函数。如果n秒内该事件被重新触发则重新计时。就将频繁触发的事件合并为一次,且在最后执行
直白的说就是,给定一个定长的滑动的时间段,如果两次事件之间的时间差小于这个时间段,就从最新的时间点重新计时这个时间段,直到对应时间段之内没有事件才执行实际的回调
throttle 节流
限制函数的执行频率,保证一定时间内只执行一次函数调用。无论触发频率多高,都会在指定时间间隔内执行一次函数
直白的说就是,给定一个定长的时间段,判断两次事件之间的时间差,如果大于这个时间段就执行实际的回调, 否则不做处理
设计思路
- 仓颉提供了定时器的API,借用这个API可以同时实现throttle和debounce的功能
- 仓颉是编译型语言,它提供了宏可以帮助我们在编译器生成代码,我们可以使用宏实现js中装饰器的能力
- 仓颉的Timer和iOS中的Timer一样,受到运行时以及Timer创建耗时的影响,不一定准确,会有一些偏差。
定义模式
借助仓颉中的枚举,可以轻而易举的实现模式 RepeaterMode 的定义。同时仓颉枚举和Swift中的枚举一样,可以携带参数,我们可以利用这个参数来定义throttle和debounce的时间段
定义 RepeaterConfig 方便直接使用它里面的成员变量。同样的,利用仓颉中的成员属性,可以返回对应的config对象,RepeaterConfig对象使用主构造函数构造,又省了不少代码
/**
* 模式,时间为毫秒
*/
public enum RepeaterMode {
| Leading(Int)
| Trailing(Int)
| Both(Int)
public prop config: RepeaterConfig {
get() {
match (this) {
case Leading(interval) => RepeaterConfig(
interval: Duration.millisecond * interval,
leading: true,
trailing: false
)
case Trailing(interval) => RepeaterConfig(
interval: Duration.millisecond * interval,
leading: false,
trailing: true
)
case Both(interval) => RepeaterConfig(
interval: Duration.millisecond * interval,
leading: true,
trailing: true
)
}
}
}
}
/**
* 属性配置
*/
public struct RepeaterConfig {
/**
* interval 等待间隔时间(毫秒)
* leading在开头调用
* trailing在最后调用
*/
public RepeaterConfig(
var interval!: Duration,
var leading!: Bool = false,
var trailing!: Bool = true
) {}
}
定义Repeater
定义一个Repeater类来实现throttle和debounce的功能。该类提供两个构造函数,既可以接收mode也可以接收config,方便通过宏@Debounce和@Throttle使用以及直接通过类Repeater使用
public class Repeater {
private var lastCallTime: MonoTime = getNowTime()
private var lastRunTaskTime: MonoTime = getNowTime()
private var firstRunTask: Bool = false
// 定时器,只有trailing才会使用
private var timer: ?Timer = None
// 配置和任务
private let config: RepeaterConfig
private let task: RepeaterTask
private let throttle: Bool
public init(throttle!: Bool, mode!: RepeaterMode, task!: RepeaterTask) {
this(throttle: throttle, config: mode.config, task: task)
}
public init(throttle!: Bool, config!: RepeaterConfig, task!: RepeaterTask) {
this.config = config
this.task = task
this.throttle = throttle
this.verifyConfig()
}
...
}
使用方式
就像上面我们说的,我们既可以通过Repeater类来使用,也可以通过提供的宏来使用
通过Repeater类
let start = getNowTime()
let debouncer = Repeater(throttle: false, mode: Trailing(100)) {
println('testDebounce执行间隔 ${getNowTime()-start}')
}
debouncer.call()
通过宏
class RepeaterMemberMacro {
let start = getNowTime()
@Debounce[100]
func myDebounce() {
println('myDebounce执行间隔 ${getNowTime()-start}')
}
@Throttle[50]
func myThrottle() {
println('myThrottle执行间隔 ${getNowTime()-start}')
}
}
工具地址
欢迎大家体验完善