throttle
swift
let subject = PublishSubject<String>()
let _ = subject
.throttle(.seconds(1), scheduler: MainScheduler())
.subscribe(onNext: { str in
debugPrint(str)
})
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
subject.onNext("4")
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
subject.onNext("5")
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
subject.onNext("6")
}
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
subject.onNext("7")
}
输出结果为
1
5
7
throttle实现原理
从原理分析 throttle
,实现如下
swift
// 用 Timer 实现
class Throttle {
var timer: Timer?
func throttle(_ second: Int, _ completion: @escaping ( () -> Void )) {
// 当timer运行期间,在接受到的事件则直接return
if timer?.isValid == true {
return
}
completion()
timer = Timer.scheduledTimer(withTimeInterval: TimeInterval(second), repeats: false, block: { (tm) in
self.cleanTimer()
})
RunLoop.current.add(timer!, forMode: .common)
}
func cleanTimer() {
timer?.invalidate()
timer = nil
}
}
// 记录执行事件
class Throttle {
var dueTime: CFTimeInterval = -1
func throttle(_ second: Int, _ completion: @escaping ( () -> Void )) {
// 当timer运行期间,在接受到的事件则直接return
if CACurrentMediaTime() - dueTime < second {
return
}
dueTime = CACurrentMediaTime()
}
}
回到最上方 throttle
的例子,如果假如每0.1s发出一个信号,则 throttle
会保证每1s执行下订阅的内容
debounce
swift
let subject = PublishSubject<String>()
let _ = subject
.debounce(.seconds(1), scheduler: MainScheduler())
.subscribe(onNext: { str in
debugPrint(str)
})
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
subject.onNext("4")
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
subject.onNext("5")
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
subject.onNext("6")
}
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
subject.onNext("7")
}
输出结果为
4
7
也就是 debounce
会对小于设定时间内的连续触发事件进行去重,当最后一个时间输入后大于设定时间才会发出通知
探讨debounce实现原理
从原理分析 debounce
,实现如下
swift
// 用 Timer 实现
class Debounce {
var timer: Timer?
func throttle(_ second: Int, _ completion: @escaping ( () -> Void )) {
self.cleanTimer()
timer = Timer.scheduledTimer(withTimeInterval: TimeInterval(second), repeats: false, block: { (tm) in
completion()
self.cleanTimer()
})
RunLoop.current.add(timer!, forMode: .common)
}
func cleanTimer() {
timer?.invalidate()
timer = nil
}
}
回到最上方 debounce
的例子,如果假如每0.1s发出一个信号,则 debounce
将一直无法执行订阅中的内容,当停止发出信号后1s,才会执行一次订阅中的内容