RxSwift Single과 Observable에 대한 실험
RxSwift에서 Single로 생성한 Observable과 Observable로 생성한 Observable에서 이벤트를 각각 방출하고, 서로 반대로 Observable → asSingle, Single → asObservable을 했을 때, 어떤 차이점이 있을지 궁금해서 테스트를 해보았습니다.
[Single] vs [Observable]
- Observable로 만들어진 스트림을 asSingle로 했을 때와 Single로 만들어진 스트림을 asObservable로 했을 때의 차이점을 알아보기 위해 실험을 하였습니다.
Single로 만들어진 스트림을 Observable로 했을 경우
- 코드
override func viewDidLoad() {
super.viewDidLoad() print("=============== Observable Result ===============")
issueObservable.asObservable()
.subscribe(onNext: { d in print("onNext: \\\\(d)")
}, onError: { e inprint("onError: \\\\(e)")
}, onCompleted: {
print("onCompleted")
}, onDisposed: {
print("onDisposed")
}).disposed(by: disposeBag) print("=============== Single Result ===============")
issueObservable
.subscribe(onSuccess: { d in print("onSuccess: \\\\(d)")
}, onError: { e in print("onError: \\\\(e)")
}).disposed(by: disposeBag)
}var issueSingle: Single<Int> {
return createSingle()
}func createSingle() -> Single<Int> { return Single.create { emitter in emitter(SingleEvent.success(3))
emitter(SingleEvent.success(4))
emitter(SingleEvent.success(5))
emitter(SingleEvent.success(6)) return Disposables.create()
}
}
- 결과
=============== Observable Result ===============
onNext: 3
onCompleted
onDisposed
=============== Single Result ===============
onSuccess: 3
- 위의 결과를 보면 Single에서 success이벤트를 여러번 수행하더라도 asObservable로 받아온 스트림에서는 onNext를 한번 수행하고, 바로 onCompleted를 수행하는 것을 볼 수 있습니다. 그리고 onDisposed까지 수행하는 것으로 보아, Single로 구현된 스트림에서는 한번의 success이벤트 수행으로 스트림 자체를 dispose까지 시켜버리는 것으로 확인했습니다.
- single 스트림에서는 onSuccess를 한 번 수행한 것으로 끝났습니다.
Observable로 만들어진 스트림을 Single로 했을 경우
- 코드
override func viewDidLoad() {
super.viewDidLoad() print("=============== Observable Result ===============")
issueObservable
.subscribe(onNext: { d in print("onNext: \\\\(d)")
}, onError: { e in print("onError: \\\\(e)")
}, onCompleted: {
print("onCompleted")
}, onDisposed: {
print("onDisposed")
}).disposed(by: disposeBag) print("=============== Single Result ===============")
issueObservable.asSingle()
.subscribe(onSuccess: { d in print("onSuccess: \\\\(d)")
}, onError: { e in print("onError: \\\\(e)")
}).disposed(by: disposeBag)
}var issueObservable: Observable<Int> {
return createObservable()
}func createObservable() -> Observable<Int> { return Observable.create { emitter in emitter.onNext(3)
emitter.onNext(4)
emitter.onNext(5)
emitter.onNext(6) return Disposables.create()
}
}
- 결과
=============== Observable Result ===============
onNext: 3
onNext: 4
onNext: 5
onNext: 6
=============== Single Result ===============
onError: Sequence contains more than one element.
- 위 결과를 보면 Observable로 만들어진 스트림에서는 그대로 onNext를 모두 수행하는 것을 볼 수 있었습니다.
- Single로 만들어진 스트림에서는 onNext를 여러번 수행했기 때문에 한 개보다 많은 element를 가지고 있다는 에러메시지를 보내는 것으로 확인했습니다.
추가 실험
- Single을 사용하여 받을 때는 DisposeBag에 따로 넣어주지 않더라도 success나 error 이벤트를 호출하면 알아서 dispose까지 시켜주는 것 같아서 직접 실험하였습니다.
override func viewDidLoad() {
super.viewDidLoad() print("=============== Observable Result ===============")
issueSingle.asObservable()
.subscribe(onNext: { d in print("onNext: \\\\(d)")
}, onError: { e in print("onError: \\\\(e)")
}, onCompleted: {
print("onCompleted")
}, onDisposed: {
print("onDisposed")
}) print("=============== Single Result ===============")
issueSingle
.do(onDispose: {
print("onDispose")
})
.subscribe(onSuccess: { d in print("onSuccess: \\\\(d)")
}, onError: { e in print("onError: \\\\(e)")
})
}var issueSingle: Single<Int> {
return createSingle()
}func createSingle() -> Single<Int> { return Single.create { emitter in
emitter(SingleEvent.error(NSError(domain: "", code: 1, userInfo: nil)))
emitter(SingleEvent.success(3))
emitter(SingleEvent.success(4))
emitter(SingleEvent.success(5))
emitter(SingleEvent.success(6)) return Disposables.create()
}
}
- 결과
=============== Observable Result ===============
onError: Error Domain= Code=1 "(null)"
onDisposed
=============== Single Result ===============
onError: Error Domain= Code=1 "(null)"
onDispose
핵심 결론
- Single로 만들어진 스트림을
asObservable()
을 사용하여 Observable로 만들게 되면 success를 아무리 호출해도 next이벤트 한 번과 complete이벤트 한 번 그리고 dispose 이벤트까지 호출된다. 심지어 Single로 만든 데이터 스트림에서는DisposeBag
으로 관리를 해주지 않아도 됨 - Observable로 만들어진 스트림을
asSingle()
을 사용하여 Single로 만들게 되면 complete 이벤트가 발생하기 전에 한 개 보다 많은 next 이벤트가 발생하면 에러가 발생한다.
Single 내부
이런 결과가 나오는 이유는 결국 RxSwift의 내부를 보면 됩니다.
Single의 create 메소드 안에서 success이벤트 발생시 observer가 방출하는 이벤트는 next와 complete였기 때문입니다!!
