스트림을 결합하는 연산자
🔮 마블 다이어그램 출처: https://reactivex.io/documentation/operators.html
스트림을 결합하는 연산자
두 개 이상의 스트림을 합쳐서 새로운 스트림을 만들어 내는 연산자들입니다.
startWith
특정 스트림의 맨 앞에 해당 데이터를 끼워넣는 연산자입니다. startWith의 인자로 전달된 값은 구독하자마자 바로 발행됩니다.
import RxSwift
let subject = PublishSubject<String>()
let disposeBag = DisposeBag()
subject
.startWith("발행 0")
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
print("아직 발행 안함")
subject.onNext("발행 1")
subject.onNext("발행 2")
subject.onNext("발행 3")
//🖨 출력결과
발행 0 //👉 구독하는 순간에 바로 발행됨
아직 발행 안함
발행 1
발행 2
발행 3
Concat
복수의 스트림을 이어붙이는 형식입니다. 배열에 전달된 순서로 단순히 이어 붙입니다. 이전의 스트림이 completed 되기 전 까지 다음 stream이 발행으로 해도 concat은 발행하지 않습니다.
import RxSwift
let disposeBag = DisposeBag()
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
let subject3 = PublishSubject<String>()
let observable = Observable.concat([subject1, subject2, subject3])
observable
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject1.onNext("subject1: 발행 1")
subject1.onNext("subject1: 발행 2")
subject1.onNext("subject1: 발행 3")
subject2.onNext("subject2: 발행 1") //🚫 1이 complete 되기 전에 2 발행 (출력 안됨)
subject1.onCompleted()
subject2.onNext("subject2: 발행 2")
subject3.onNext("subject3: 발행 1") //🚫 2가 complete 되기 전에 3 발행 (출력 안됨)
subject2.onCompleted()
subject3.onNext("subject3: 발행 2")
//🖨 출력 결과
subject1: 발행 1
subject1: 발행 2
subject1: 발행 3
subject2: 발행 2
subject3: 발행 2
merge
concat과 유사하게 복수의 스트림을 하나로 합칩니다. 하지만 순서대로 합쳤던 concat과는 다르게 merge는 병렬적으로 합칩니다. 따라서 합쳐진 스트림이 발행하는 대로 merge도 발행합니다.
import RxSwift
let disposeBag = DisposeBag()
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
let subject3 = PublishSubject<String>()
let observable = Observable.merge([subject1, subject2, subject3])
observable
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject3.onNext("subject3: 발행 1")
subject1.onNext("subject1: 발행 1")
subject1.onNext("subject1: 발행 2")
subject2.onNext("subject2: 발행 1")
subject1.onNext("subject1: 발행 3")
subject3.onNext("subject3: 발행 2")
subject2.onNext("subject2: 발행 2")
//🖨 출력 결과 👉 merge된 순서와 관계 없이 바로바로 발행됨
subject3: 발행 1
subject1: 발행 1
subject1: 발행 2
subject2: 발행 1
subject1: 발행 3
subject3: 발행 2
subject2: 발행 2
combineLatest
복수의 스트림을 짝지어 발행합니다. 만약 짝을 지을 수 없다면 발행하지 않습니다.
한 스트림에서 데이터가 발행되면 다른 스트림의 가장 최근에 발행된 값들과 짝 지어 발행됩니다. 즉 이미 모든 스트림이 1번 이상 발행이 되었다면 어떤 스트림이든 발행되는 순간 combineLatest는 발행됩니다.
짝 짓는다는 표현을 사용했지만 3개 이상의 스트림을 합칠 수도 있습니다.
짝을 지어 발행하는 데이터의 형태를 정의하는 resultSelector라는 클로저를 가질 수 있습니다. (생략될 경우 배열의 형태로 발행됩니다.)
2개의 스트림 합치기
import RxSwift
let disposeBag = DisposeBag()
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
let subject3 = PublishSubject<String>()
let observable = Observable.combineLatest(subject1, subject2) { s1, s2 in
"\(s1) 그리고 \(s2)"
}
//let observable = Observable.combineLatest([subject1, subject2, subject3])
observable
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject1.onNext("subject1: 발행 1")
subject1.onNext("subject1: 발행 2")
subject2.onNext("subject2: 발행 1") //👉 짝 지어져서 발행 시작!
subject1.onNext("subject1: 발행 3")
subject2.onNext("subject2: 발행 2")
//🖨 출력 결과
subject1: 발행 2 그리고 subject2: 발행 1 //👉 resultSelector에서 정의한 String의 모습
subject1: 발행 3 그리고 subject2: 발행 1
subject1: 발행 3 그리고 subject2: 발행 2
3개 이상 스트림 합치기
import RxSwift
let disposeBag = DisposeBag()
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
let subject3 = PublishSubject<String>()
let observable = Observable.combineLatest([subject1, subject2, subject3])
observable
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject3.onNext("subject3: 발행 1")
subject1.onNext("subject1: 발행 1")
subject1.onNext("subject1: 발행 2")
subject2.onNext("subject2: 발행 1") //👉 이 때 모든 스트림이 1번 이상 발행되면서 짝이 지어짐
subject1.onNext("subject1: 발행 3")
subject3.onNext("subject3: 발행 2")
subject2.onNext("subject2: 발행 2")
//🖨 출력 결과
["subject1: 발행 2", "subject2: 발행 1", "subject3: 발행 1"]
["subject1: 발행 3", "subject2: 발행 1", "subject3: 발행 1"]
["subject1: 발행 3", "subject2: 발행 1", "subject3: 발행 2"]
["subject1: 발행 3", "subject2: 발행 2", "subject3: 발행 2"]
withLatestFrom
첫 번째 스트림이 발행될 때 두 번째 스트림의 가장 최근 데이터와 짝지어 발행됩니다. 마찬가지로 짝 지을 수 없다면 발행되지 않습니다.
combineLatest와 거의 동일하지만 제 3의 스트림을 만드는 combine과는 달리 기존 스트림에 연산자로 다른 스트림을 바로 결합할 수 있습니다.
resultSelector를 정의하지 않은 경우
첫 번째 스트림은 trigger의 역할만 수행하고 두 번째 스트림의 데이터만 발행됩니다.
import RxSwift
let disposeBag = DisposeBag()
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
let observable = subject1.withLatestFrom(subject2)
subject1
.withLatestFrom(subject2)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject2.onNext("1")
subject2.onNext("2")
subject1.onNext("A")
subject2.onNext("3")
subject2.onNext("4")
subject1.onNext("B")
//🖨 출력 결과
2
4
resultSelector를 정의한 경우
정의한 클로저의 return 값을 발행합니다.
import RxSwift
let disposeBag = DisposeBag()
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
let observable = subject1.withLatestFrom(subject2)
subject1
.withLatestFrom(subject2) { "\($0)\($1)" }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject2.onNext("1")
subject2.onNext("2")
subject1.onNext("A")
subject2.onNext("3")
subject2.onNext("4")
subject1.onNext("B")
//🖨 출력 결과
A2
B4
Author And Source
이 문제에 관하여(스트림을 결합하는 연산자), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@comdongsam/스트림을-결합하는-연산자저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)