Taking Operator
Skip -> 전 무시
Take -> 후 무시
take 는 skip 의 반대 개념으로
skip 은 인자로 보내는 index 만큼의 시퀀스를 무시합니다.
take 는 반대로 인자로 보내는 count 만큼의 시퀀스만 방출합니다.
코드로 좀더 알기 쉽게 설명하면
Observable<Int>
.from([1,2,3,4,5,6])
.take(2)
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
/*
print
1
2
*/
take(untill:) 은 skip(untill:) 의 반대 개념입니다.
skip(untill:) 의 개념은
take는 Trigger 시퀀스의 방출이 시작되기 전까지의 요소들만 방출합니다.
let sub = PublishSubject<Int>() //Subscribe 시퀀스
let trg = PublishSubject<Int>() //Trigger 시퀀스
sub
.take(until: trg) // Trigger 시퀀스 감시 하기
.subscribe(onNext: { // 구독
print($0)
}).disposed(by: disposeBag)
sub.onNext(1) // Subscribe 시퀀스 방출시작. 방출
sub.onNext(3) // 방출
trg.onNext(4) // Trigger 시퀀스 방출시작.
sub.onNext(5) // 무시
sub.onNext(6) // 무시
/*
print
1
3
*/
take 와 skip 은 서로 와 정반대의 성질을 띄고 있습니다.
while 또한 skip(while:) 의 경우
크게 보면 이렇게 볼수 있습니다.
take(while:)의 경우는
Observable<String>
.from(["1","1","1","2","2","3","1"])
.take(while: { $0 == "1"})
.subscribe(onNext : {
print($0)
}).disposed(by: disposeBag)
/*
print
1
1
1
*/
이러한 output을 볼수 있습니다.
takeLast 는 시퀀스의 뒤에서 부터 지정하는 count 만큼의 요소를 방출 시킵니다.
Observable<String>
.from(["1","1","1","2","2","3","1"])
.takeLast(3)
.subscribe(onNext : {
print($0)
}).disposed(by: disposeBag)
/*
print
2
3
1
*/
중복값 무시
distinctUntilChanged 는 시퀀스 에는 중복값을 Filtering 해줍니다.
Observable<String>
.from(["1","1","1","2","2","3","1"])
.distinctUntilChanged()
.subscribe(onNext : {
print($0)
}).disposed(by: disposeBag)
/*
print
1
2
3
1
*/
여기서 자세히 볼필요가 있는 부분은 연속 이라는 점 같습니다.
중복되는 Event 가 연속적으로 발생할시 중복 값을 무시하지만
중복되지 않는 Event 발생후 다시 중복되는 Event가 방출되면 무시 하지 못합니다.
연속적으로 들어오는 중복값만 무시
특정 시간 동안 Event 를 방출하지 않고 시간이 경과되어야 Event 방출
debounce 는 dueTime 와 scheduler 를 지정합니다.
지정한 scheduler 안에서 지정된 dueTime 안에서 벌어지는 Event는 방출하지 않고
지정된 시간 외에 발생하는 가장 최근 Event 만 Emit 합니다.
또한 Event 가 Emit 되면 Timer 는 초기화 됩니다.
여러번 Emit 되는 Event 들에 대응하기 좋은 Operator 라고 생각 됩니다.
어떠한 Event 방출에도 제한한 시간 외 에서의 최근 Event 만을 방출하기 때문에
사용자 의 연속적인 입력에 대비하기 좋고 자동완성 / 연관검색어 완성 부분에서 사용하기 유용할것 같습니다.
Observable<Int>.interval(.seconds(2), scheduler: MainScheduler.instance)
.take(10)
.debounce(.seconds(1), scheduler: MainScheduler.instance)
.debug("호호호히히히")
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
/*
print
2022-02-18 17:41:36.881: 호호호히히히 -> subscribed
2022-02-18 17:41:39.885: 호호호히히히 -> Event next(0)
0
2022-02-18 17:41:41.884: 호호호히히히 -> Event next(1)
1
2022-02-18 17:41:43.884: 호호호히히히 -> Event next(2)
2
2022-02-18 17:41:45.884: 호호호히히히 -> Event next(3)
3
2022-02-18 17:41:47.883: 호호호히히히 -> Event next(4)
4
2022-02-18 17:41:49.884: 호호호히히히 -> Event next(5)
5
2022-02-18 17:41:51.883: 호호호히히히 -> Event next(6)
6
2022-02-18 17:41:53.884: 호호호히히히 -> Event next(7)
7
2022-02-18 17:41:55.884: 호호호히히히 -> Event next(8)
8
2022-02-18 17:41:56.883: 호호호히히히 -> Event next(9)
9
2022-02-18 17:41:56.884: 호호호히히히 -> Event completed
2022-02-18 17:41:56.884: 호호호히히히 -> isDisposed
*/
Throttle 은 트위터에서 스크롤 버벅거림 관련 이슈를 해결하기 위해 제안한 방법론 이라고 합니다.
Throttle 은 Event 가 Emit 되면 dueTime 에 지정된 시간 안 에서 2개 이상의 Event 가 Emit 되지 않습니다.
// tap , throttle
buttonName.rx.tap
.asObservable()
.throttle(.milliseconds(500), scheduler: MainScheduler.instance)
.withUnretained(self) // 약한참조
.bind(onNext : { _ , _ in
print("바인드 코드")
}).disposed(by: disposeBag)
버튼에 API 호출 트리거가 있는 경우, lastest = false 파라미터를 통해 유저의 첫 번째 클릭만 이벤트 방출이 되게하여 API 중복 호출을 막는다.
무한 스크롤(인피니티 스크롤) 구현할 때에도, 페이지 별 데이터를 가져오기 위해 API를 호출해야하기 때문에, 유저 스크롤 이벤트에 throttle을 사용하면 API Call 비용을 줄일 수 있다.
연이어서 API 호출될 수 있을 때, 마지막 이벤트를 기준으로 API를 호출시킬 수 있도록 제한이 필요할 때 사용할 수 있다