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

相关推荐
Csvn7 小时前
WASM
前端
修己xj8 小时前
我用 AI 给自己写了一个 Markdown 编辑器,然后把它开源了
前端
FRing038 小时前
vue2干货总结2(v-bind、v-for、v-model、指令修饰符、v-bind操作class和style)
开发语言·前端·vue.js·vue2
幸运小猿9 小时前
模拟慢上传-处理超时重试image 丢失线上问题
前端·javascript·html
moshuying10 小时前
网购能买Token了!
前端
h_654321010 小时前
echarts实现柱状图加一条横线
前端·echarts
风骏时光牛马11 小时前
生成一个后端标题,只需要一个标题,不需要其他的任何文本。
前端
子非鱼@Itfuture11 小时前
关于前后端联调中登录状态/登录信息失效?
java·前端
郭小李11 小时前
openFeign入门
java·开发语言·前端
馒头不想说话11 小时前
AI当运营,帮你省人力
前端