이번 포스트에서는 Observable의 이벤트를 수를 맞춰서 합쳐주는 zip 연산자를 알아보겠습니다.

zip

zip은 combineLatest와 이름빼고 거의 동일한 시그니처를 가집니다. 여러 Observable을 인자로 받을 수 있도록 선언되어 있고, 8개까지 정의되어 있다는 것 까지 동일합니다.

 public static func zip<O1: ObservableType, O2: ObservableType>
        (_ source1: O1, _ source2: O2, resultSelector: @escaping (O1.Element, O2.Element) throws -> Element)
        -> Observable<Element> {
        return Zip2(
            source1: source1.asObservable(), source2: source2.asObservable(),
            resultSelector: resultSelector
        )
    }

combineLatest와의 차이는 이벤트를 내보내는 정책입니다. zip은 각 Observable이 내보내는 이벤트들을 내부적으로 가지고 있다가, 동일한 인덱스를 가진 이벤트들을 묶어 내보냅니다. 만약 인자로 주어진 Observable중 하나라도 종료된다면, 전체가 종료되어 버립니다.

let timer1 = Observable<Int>.interval(RxTimeInterval.seconds(1), scheduler: MainScheduler.instance).map({"o1: \($0)"})
let timer2 = Observable<Int>.interval(RxTimeInterval.seconds(2), scheduler: MainScheduler.instance).map({"o2: \($0)"})

Observable.zip(timer1,timer2)
    .subscribe { event in
        switch event {
        case let .next(value):
            print(value)
        default:
            print("finished")
        }
        
    }.disposed(by: bag)
// ("o1: 0", "o2: 0")
// ("o1: 1", "o2: 1")
// ("o1: 2", "o2: 2")
// ("o1: 3", "o2: 3")
// ...

zip을 이용해서 산발적으로 발생하는 이벤트를 동일한 순서로 동일한 때에 처리할 수 있습니다.