[Single] vs [Observable]

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가 방출하는 이벤트는 nextcomplete였기 때문입니다!!

끄읏😜 -

--

--

https://www.notion.so/iOS-7a979d77a48247c890285a9a085cda9f

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store