debounce, throttle는 짧은 시간동안 반복적으로 방출되는 이벤트를 제어한다는 공통점이 있다.
연산자로 전달하는 파라미터도 동일하다.
하지만 연산의 결과는 완벽히 다르기 때문에 잘 구분해서 사용해야한다.
공통
let buttonTap = Observable<String>.create { observer in
DispatchQueue.global().async {
//0.3초 주기로 nextEvent를 10번 방출한다
for i in 1...10 {
observer.onNext("Tap \(i)")
Thread.sleep(forTimeInterval: 0.3)
}
//1초동안 중지하고
Thread.sleep(forTimeInterval: 1)
//0.5초 주기로 10번 방출한다
for i in 11...20 {
observer.onNext("Tap \(i)")
Thread.sleep(forTimeInterval: 0.5)
}
observer.onCompleted()
}
return Disposables.create {
}
}
//next(Tap 1)
//next(Tap 2)
//next(Tap 3)
//next(Tap 4)
//next(Tap 5)
//next(Tap 6)
//next(Tap 7)
//next(Tap 8)
//next(Tap 9)
//next(Tap 10)
//next(Tap 11)
//next(Tap 12)
//next(Tap 13)
//next(Tap 14)
//next(Tap 15)
//next(Tap 16)
//next(Tap 17)
//next(Tap 18)
//next(Tap 19)
//next(Tap 20)
//completed
debounce
두개의 파라미터를 갖는다.
첫 번째 파라미터에는 시간을 전달한다.
이 시간은 연산자가 넥스트이벤트를 방출할지 결정하는 조건으로 사용된다.
옵저버가 넥스트이벤트를 방출한 다음 일정 시간동안 다른 이벤트를 방출하지 않는다면 해당시점에 가장 마지막으로 방출된 이벤트를 구독자에게 전달한다. 반대로 지정된 시간 이내에 또다른 nextEvent를 방출했다면 타이머를 초기화한다.
타이머를 초기화한 다음에 다시 지정된 시간동안 대기한다.
이 시간 이내에 다른 이벤트가 방출되지 않는다면 이벤트를 방출하고
다른 이벤트가 방출된다면 타이머를 초기화한다.
두번째 파라미터에는 타이머를 스케쥴링할 스케쥴러가 들어간다.
buttonTap
.debounce(.milliseconds(1000), scheduler: MainScheduler.instance)
.subscribe { print($0) }
.disposed(by: disposeBag)
//next(Tap 10)
//next(Tap 20)
//completed
debounce연산자는 지정된 시간동안 새로운 이벤트가 방출되지 않으면 가장 마지막에 방출된 방출된 이벤트를 구독자에게 전달한다.
throttle
debounce연산자와 마찬가지로 2개를 파라미터로 받지만 실제론 3개를 파라미터로 받는다.
기본값을 가진 두번째 연산자의 파라미터를 생략하는 경우가 많기 때문이다.
첫 번째 파라미터에는 반복 주기를 전달한다
세 번째 파라미터는 스케쥴러를 전달한다.
throttle은 지정된 주기동안 하나의 이벤트만 구독자에게 전달한다.
보통 두번째 파라미터는 기본값을 사용하는데 이때는 주기를 엄격하게 지킨다. 항상 지정된 주기마다 하나씩 이벤트를 전달한다. 반대로 false를 전달하면 반복 주기가 경과한 다음 가장 먼저 방출되는 이벤트를 구독자에게 전달한다.
buttonTap
.throttle(.milliseconds(1000), scheduler: MainScheduler.instance)
.subscribe { print($0) }
.disposed(by: disposeBag)
//next(Tap 1)
//next(Tap 4)
//next(Tap 7)
//next(Tap 10)
//next(Tap 11)
//next(Tap 12)
//next(Tap 14)
//next(Tap 16)
//next(Tap 18)
//next(Tap 20)
//completed
이번엔 원본 옵저버블이 방출하는 nextevent를 1초마다 하나씩 방출한다.
짧은 시간동안 반복되는 tapevent나 delegate 메세지를 처리할 때에는 보통 throtle연산자를 활용한다.
debounce는 보통 검색기능을 구현할 때 사용된다.
사용자가 키워드를 입력할때마다 네트워크를 요청하거나 데이터베이스를 검색해야 한다고 가정한다.
문자가 입력될 때 마다 매번 작업을 실행하는 것은 효율적이지 않다. debounce를 사용하면 사용자가 짧은 시간동안 연속해서 문자열을 입력할 때에는 작업이 실행되지 않는다. 그러다가 지정된 시간동안 문자열을 입력하지 않으면 검색작업을 실행한다.
불필요한 리소스를 잡아먹지 않으면서 실시간 검색기능을 완성할 수 있다.