RxSwift中throttle和debounce区别及实现原理

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,才会执行一次订阅中的内容

相关推荐
Fan_web2 分钟前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常4 分钟前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式
莹雨潇潇1 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
Jiaberrr1 小时前
Element UI教程:如何将Radio单选框的圆框改为方框
前端·javascript·vue.js·ui·elementui
Tiffany_Ho2 小时前
【TypeScript】知识点梳理(三)
前端·typescript
安冬的码畜日常3 小时前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
小白学习日记3 小时前
【复习】HTML常用标签<table>
前端·html
丁总学Java4 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
yanlele4 小时前
前瞻 - 盘点 ES2025 已经定稿的语法规范
前端·javascript·代码规范