ย Time-based Operator
Time-shifting Operator
์ด๋ฒคํธ ๋ฐฉ์ถ์ ์ง์ฐ์ํฌ ์ ์๋ ์ฐ์ฐ์์
๋๋ค.
delaySubscription
๊ตฌ๋
์ด ์์๋๋ ์์ ์ ์ง์ฐ
delaySubscription์ ๊ตฌ๋
์ด ์์๋๋ ์์ ์ด ์ง์ฐ๋๋๊ฑฐ์ง, next ์ด๋ฒคํธ์ ์ ๋ฌ์ ์ง์ฐ๋์ง ์๊ณ ๋ฐ๋ก ์ ๋ฌ๋ฉ๋๋ค.
Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
.take(6)
.delaySubscription(.seconds(3), scheduler: MainScheduler.instance)
.subscribe { print($0) }
.disposed(by: disposeBag)
/*
3์ด๊ฐ ์ง๋ ํ์...
next(0)
next(1)
next(2)
next(3)
next(4)
next(5)
completed
*/
Swift
๋ณต์ฌ
delay
next ์ด๋ฒคํธ๊ฐ ์ ๋ฌ๋๋ ์์ ์ ์ง์ฐ
delaySubscription๊ณผ๋ ๋ฐ๋๋ก ๊ตฌ๋
์์ ์ ์ง์ฐ์ํค์ง ์๊ณ , next ์ด๋ฒคํธ์ ์ ๋ฌ์ ์ง์ฐ์ํต๋๋ค.
Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
.take(6)
.debug()
.delay(.seconds(3), scheduler: MainScheduler.instance)
.subscribe { print($0) }
.disposed(by: disposeBag)
// subscribed๋ ์ง์ฐ๋์ง ์์ง๋ง, next ์ด๋ฒคํธ๊ฐ ๋์ค๋๊ฑด 3์ด ๋ค๋ถํฐ
/*
(bind()) -> subscribed
(bind()) -> Event next(0)
(bind()) -> Event next(1)
(bind()) -> Event next(2)
(bind()) -> Event next(3)
next(0)
(bind()) -> Event next(4)
next(1)
(bind()) -> Event next(5)
(bind()) -> Event completed
(bind()) -> isDisposed
next(2)
next(3)
next(4)
next(5)
completed
*/
Swift
๋ณต์ฌ
Timer Operator
์ด๋ฒคํธ๊ฐ ๋ฐฉ์ถ๋๋ ์๊ฐ ๊ฐ๊ฒฉ์ ์ค์ ๊ฐ๋ฅํ ์ฐ์ฐ์์
๋๋ค.
interval
์ง์ ๋ ์ฃผ๊ธฐ๋ง๋ค ์ ์ ํ์
์ ๊ฐ์ ๋ฐฉ์ถ
์ง์ ๋ ์ฃผ๊ธฐ๋ง๋ค ์ ์ ํ์
์ ๊ฐ์ ์ง์์ ์ผ๋ก ๋ฐํํฉ๋๋ค. ๋ฐ๋ผ์, ํด๋น Observable์ ์ค์งํ๊ธฐ ์ํด์๋ .take ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ๋ฐํ๋๋ ์ด๋ฒคํธ์ ์๋ฅผ ์ ํํ๊ฑฐ๋, dispose๋ฅผ ์ง์ ํธ์ถํด์ผ ํฉ๋๋ค.
Observable<Int>
.interval(.nanoseconds(1), scheduler: MainScheduler.instance)
.take(until: { $0 == 20 }, behavior: .inclusive)
.subscribe { print($0, terminator: " ") }
.disposed(by: disposeBag)
/*
next(0) next(1) next(2) next(3) next(4) next(5) next(6) next(7) next(8) next(9) next(10) next(11) next(12) next(13) next(14) next(15) next(16) next(17) next(18) next(19) next(20) completed
*/
Swift
๋ณต์ฌ
timer
์ง์ฐ ์๊ฐ๊ณผ ๋ฐ๋ณต ์ฃผ๊ธฐ๋ฅผ ์ง์ ํด์ ์ ์ ํ์
์ ๊ฐ ๋ฐฉ์ถ
timer๋ interval๊ณผ ๋์ผํ๊ฒ Observable์ ์ค์งํ๊ธฐ ์ํด์๋ .take๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ๋ฐํ๋๋ ์ด๋ฒคํธ ์๋ฅผ ์ ํํ๊ฑฐ๋, dispose๋ฅผ ์ง์ ํธ์ถํด์ผ ํฉ๋๋ค. interval๊ณผ๋ ๋ค๋ฅด๊ฒ dueTime๋ฅผ ์ถ๊ฐํด์ ์ด๋ฒคํธ ๋ฐํ์ด ์ง์ฐ๋๋ ์๊ฐ์ ๋ง๋ค ์ ์์ต๋๋ค.
Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)
.take(until: { $0 == 10 }, behavior: .inclusive)
.subscribe{ print($0, terminator: " ") }
.disposed(by: disposeBag)
/*
next(0) next(1) next(2) next(3) next(4) next(5) next(6) next(7) next(8) next(9) next(10) completed
*/
Swift
๋ณต์ฌ
timeout
์ง์ ๋ ์๊ฐ ์ด๋ด์ ์์๋ฅผ ๋ฐฉ์ถํ์ง ์์ผ๋ฉด ์๋ฌ ์ด๋ฒคํธ ์ ๋ฌ
โข
์๋ฌ ๋ฐฉ์ถ
let subject = PublishSubject<Int>()
subject.timeout(.seconds(3), scheduler: MainScheduler.instance)
.subscribe{ print($0) }
.disposed(by: disposeBag)
// ์๋ฌด๋ฐ ์ด๋ฒคํธ๋ ๋ฐฉ์ถ๋์ง ์์์ 3์ด ๋ค์ ์๋ฌ ์ด๋ฒคํธ๊ฐ ์ ๋ฌ
/*
error(Sequence timeout.)
*/
Swift
๋ณต์ฌ
โข
์ ์ ์๋
let subject = PublishSubject<Int>()
subject.timeout(.seconds(3), other: Observable.just(1), scheduler: MainScheduler.instance)
.subscribe{ print($0) }
.disposed(by: disposeBag)
Observable<Int>.timer(.seconds(2), period: .seconds(5), scheduler: MainScheduler.instance)
.subscribe(onNext: { subject.onNext($0) })
.disposed(by: disposeBag)
// ์ด๋ฒคํธ๊ฐ ๋ฐฉ์ถ๋๊ธฐ ๋๋ฌธ์ ์๋ฌ ์ด๋ฒคํธ๊ฐ ์ ๋ฌ๋์ง ์์
/*
next(0)
next(1)
completed
*/
Swift
๋ณต์ฌ
debounce
ํ์ด๋จธ๋ฅผ ์ง์ ํด๋๊ณ ํ์ด๋จธ๊ฐ ๋๋ ์์ ์ ๊ฐ์ฅ ์ต๊ทผ์ ๊ฐ์ ๋ฐฉ์ถ
์ฐ์์ ์ธ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋, ํน์ ์๊ฐ ๋ฒ์๋์ ๋ค๋ฅธ ์ด๋ฒคํธ๊ฐ ๋ฐ์๋์ง ์๋๋ค๋ฉด ๊ฐ์ฅ ๋ง์ง๋ง์ ๋ฐ์ํ ์ด๋ฒคํธ๋ง ๋ฐฉ์ถ๋๊ณ ๋๋จธ์ง ์ฐ์์ ์ธ ์ด๋ฒคํธ๋ blockํด์ฃผ๋ ์ญํ ์ ํฉ๋๋ค.
debounce๋ ์ด๋ฒคํธ๊ฐ ๋ฐฉ์ถ๋ ๋๋ง๋ค ํ์ด๋จธ๊ฐ ์ด๊ธฐํ๋ฉ๋๋ค.
textField.rx.text.orEmpty
.debounce(.seconds(1), scheduler: MainScheduler.asyncInstance)
.subscribe(onNext: { text in
print(text)
})
.disposed(by: disposeBag)
// ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ์งํ 1์ด๋์ ์ด๋ ํ ๋ค๋ฅธ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ง ์๋๋ค๋ฉด ๊ทธ๋๋ก ์ด๋ฒคํธ๊ฐ ๋ฐฉ์ถ๋๊ณ ,
// ์ฐ์์ ์ผ๋ก ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ค๋ฉด block ํด์ฃผ๋ ์ญํ
Swift
๋ณต์ฌ
throttle
ํ์ด๋จธ๋ฅผ ์ง์ ํด๋๊ณ ์ด๋ฒคํธ๊ฐ ์ฒ์ ๋ฐฉ์ถ๋๋ฉด ์ง์ ๋ ์๊ฐ๋์ ์ด๋ค ์ด๋ฒคํธ๋ ๋ฐฉ์ถํ์ง ์์
throttle๋ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ ์ต์ ๊ฐ๊ฒฉ์ ์ ํํ ์ ์๋ Operator์
๋๋ค. ์ด๋ค ์ด๋ฒคํธ๊ฐ ๋ฐฉ์ถ๋๋ ์์ ์์ ์ง์ ํ ์๊ฐ๋์ ์ด๋ฒคํธ๋ค์ blockํจ์ผ๋ก์จ, ์ด๋ฒคํธ๊ฐ ๋ฐฉ์ถ๋๋ ๊ฐ๊ฒฉ์ ์ ํํ ์ ์์ต๋๋ค.
โข
latest = true
throttle์๋ latest๋ผ๋ ๋งค๊ฐ๋ณ์๊ฐ ์๋๋ฐ ํด๋น ์์ญ์ true๋ก ์ค์ ํ๊ฒ ๋๋ฉด, ์ง์ ์๊ฐ ๋ค์ ๊ฐ์ฅ ์ต๊ทผ ๊ฐ์ ํ ๋ฒ ๋ ๋ฐฉ์ถํ๊ฒ ๋ฉ๋๋ค.
Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
.take(10)
.throttle(.seconds(2), latest: true, scheduler: MainScheduler.instance)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
// emit(0) - 1 - emit(2) - 3 - emit(4) - 5 - emit(6) - 7 - emit(8) - 9 - emit(9) - completed
/*
0
2
4
6
8
9
*/
Swift
๋ณต์ฌ
โข
latest = false
latest๊ฐ false๋ฉด ์ฒ์ ๋ฐฉ์ถ๋ ์ด๋ฒคํธ๋ง ๋ฐฉ์ถ๋๊ณ ํ์ด๋จธ ์๊ฐ๋์ ์ด๋ค ์ด๋ฒคํธ๋ ๋ฐฉ์ถ๋์ง ์์ต๋๋ค.
Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
.take(10)
.throttle(.seconds(2), latest: false, scheduler: MainScheduler.instance)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
// emit(0) - 1 - emit(2) - 3 - emit(4) - 5 - emit(6) - 7 - emit(8) - 9 - completed
/*
0
2
4
6
8
*/
Swift
๋ณต์ฌ
debounce์ throttle๋ ๋น์ทํด ๋ณด์
๋๋ค. ์ฐจ์ด๊ฐ ์๋์?
โข
debounce
debounce๋ ์ฌ๋ฌ ๋ฒ ๋ฐ์ํ๋ ์ด๋ฒคํธ์์, ๊ฐ์ฅ ๋ง์ง๋ง ์ด๋ฒคํธ๋ง์ ์คํ๋๋๋ก ๋ง๋๋ ๊ฐ๋
์
๋๋ค.
์ฆ, ์๊ฐ ๊ฐ์ด 1์ด์ผ ๋ ์ค๋ณต์ผ๋ก 99์ด๋์ 100๋ฒ ๋๋ฅด๋ฉด 1๋ฒ ๋ฐ์๋๋ ๊ฒ์ด debounce ์
๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์, debounce๋ ์๋์์ฑ์ด๋ ์ฐ๊ด๊ฒ์์ด ๋
ธ์ถ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ ํฉํฉ๋๋ค.
ํ
์คํธ ํ๋์ ํ
์คํธ๊ฐ ์ฌ๋ฌ๋ฒ ๋ค์ด์ค๋ ๋์์ ํด๋น ํ
์คํธ๋ฅผ ๋ฐฉ์ถํ์ง ์๋ค๊ฐ ์ ๊น ๋ฉ์ถ๋ ๋์ ํด๋น ํ
์คํธ๋ฅผ ์๋์์ฑํ๊ฑฐ๋ ์ฐ๊ด๊ฒ์์ด๋ฅผ ๋ถ๋ฌ์ค๋ ๊ฒ์ด์ฃ . ์๋๋ผ๋ฉด, ์๋ฒ์ ํด๋น ํ
์คํธ๋ฅผ ๊ฒ์ํ๋ ์๊ฐ์๊ฐ์๋ ์์ฒญ์ ํ๊ฒ ๋ ๊ฒ๋๋ค.
โข
throttle
throttle๋ ์ฌ๋ฌ ๋ฒ ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ฅผ ์ผ์ ์๊ฐ๋์ ํ ๋ฒ๋ง ์คํ๋๋๋ก ๋ง๋๋ ๊ฐ๋
์
๋๋ค.
์ฆ, ์๊ฐ ๊ฐ์ด 1์ด์ผ ๋ 0.9์ด๋์ 100๋ฒ ๋๋ฅด๋ฉด 2๋ฒ ๋ฐ์(latest = true)๋ฉ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์, throttle๋ ๋ฒํผ ํญ์ด๋ ์คํฌ๋กค์ ๋ด๋ฆฌ๋ฉด์ ๋ช ์ฒ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ ๋ ์ ํฉํฉ๋๋ค.
๋ฒํผ์ ๋๋ ์ ๋, ํญ์ด ์ค๋ณต์ ์ผ๋ก ๋๋ฌ์ง๋ค๋ฉด ์๋ชป๋ ์์ฒญ์ด ์ ๋ฌ๋ ์๋ ์์ต๋๋ค. ํ์ง๋ง, ํญ์ด ๋ฐ์ํ๊ณ ๋์ ๋ช ์ด๋์ ํญ์ ํ ์ ์๋ค๋ฉด ์๋ชป๋ ๊ฐ์ด ์ ๋ฌ๋ ์ํ์ด ์ค์ด๋ค๊ฒ ๋ ๊ฒ ์
๋๋ค.