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

相关推荐
2503_928411568 分钟前
12.4 axios的二次封装-深拷贝
前端·javascript·vue.js
你真的可爱呀3 小时前
uniapp+vue3项目中的常见报错情况以及解决方法
前端·vue.js·uni-app
差点GDP7 小时前
模拟请求测试 Fake Rest API Test
前端·网络·json
酒尘&8 小时前
Hook学习-上篇
前端·学习·react.js·前端框架·react
houyhea8 小时前
从香港竹脚手架到前端脚手架:那些"借来"的发展智慧与安全警示
前端
哈哈~haha8 小时前
Step 14: Custom CSS and Theme Colors 自定义CSS类
前端·css·ui5
Ndmzi9 小时前
Matlab编程技巧:自定义Simulink菜单(理解补充)
前端·javascript·python
我命由我123459 小时前
VSCode - VSCode 修改文件树缩进
前端·ide·vscode·前端框架·编辑器·html·js
SoaringHeart10 小时前
Flutter组件封装:验证码倒计时按钮 TimerButton
前端·flutter
San30.10 小时前
深入理解 JavaScript OOP:从一个「就地编辑组件」看清封装、状态与原型链
开发语言·前端·javascript·ecmascript