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

相关推荐
Myli_ing12 分钟前
考研倒计时-配色+1
前端·javascript·考研
余道各努力,千里自同风14 分钟前
前端 vue 如何区分开发环境
前端·javascript·vue.js
软件小伟23 分钟前
Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
前端·javascript·vue.js
醉の虾1 小时前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧1 小时前
TypeScript 的发展与基本语法
前端·javascript·typescript
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
asleep7011 小时前
第8章利用CSS制作导航菜单
前端·css
hummhumm1 小时前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
幼儿园的小霸王2 小时前
通过socket设置版本更新提示
前端·vue.js·webpack·typescript·前端框架·anti-design-vue
疯狂的沙粒2 小时前
对 TypeScript 中高级类型的理解?应该在哪些方面可以更好的使用!
前端·javascript·typescript