Search

RxSwift - Observable

ย Observable

์ด๋ฒคํŠธ ๋ฐœํ–‰์˜ ์ฃผ์ฒด์ธ Observable์€ ์ด๋ฒคํŠธ๋ฅผ ์˜ˆ์˜์ฃผ์‹œํ•˜๊ณ  ์žˆ๋‹ค๊ฐ€ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ Observer์—๊ฒŒ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
Observable์ด ์ด๋ฒคํŠธ๋ฅผ ํ™•์ธํ•˜๋ฉด Observer์—๊ฒŒ ๋ฐ”๋กœ ์ „๋‹ฌํ•ด์ค˜์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— Observable๊ณผ Observer๋Š” ์—ฐ๋ฝ์„ ํ•˜๊ณ  ์žˆ๋Š” ์ƒํƒœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ƒํƒœ๋ฅผ โ€œsubscribeโ€, โ€œ๊ตฌ๋…ํ–ˆ๋‹คโ€ ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
์œ ํŠœ๋ธŒ์—์„œ ์ข‹์•„ํ•˜๋Š” ์œ ํŠœ๋ฒ„๋ฅผ ๊ตฌ๋…ํ•˜๋ฉด ํ•ด๋‹น ์œ ํŠœ๋ฒ„๊ฐ€ ์ƒˆ๋กœ์šด ์˜์ƒ์„ ์˜ฌ๋ ธ์„ ์‹œ์— ์•Œ๋ฆผ์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด์™€ ๋น„์Šทํ•˜๊ฒŒ Observable์„ ๊ตฌ๋…ํ•œ Observer๋Š” ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
Observable ์ž์ฒด๋Š” ํ•˜๋‚˜์˜ ์‚ฌ๊ฑด์ด ์•„๋‹ˆ๊ณ , ์‚ฌ๊ฑด๋“ค์˜ ์ˆœ์„œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ด๋ฒคํŠธ ๋ฐœ์ƒ์˜ ์ฃผ์ฒด์ž…๋‹ˆ๋‹ค. ์ฆ‰, Observable์€ Observable sequence, stream์ž…๋‹ˆ๋‹ค.
Observable์ด ๋ฐœํ–‰ํ•˜๋Š” ์ด๋ฒคํŠธ์˜ ํ˜•ํƒœ๋Š” ์ด 3๊ฐ€์ง€ ์ž…๋‹ˆ๋‹ค.
1.
next : ์ƒˆ๋กœ์šด ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๊ตฌ๋…์ž์—๊ฒŒ ์ „๋‹ฌ
2.
error : ์—๋Ÿฌ ๋ฐœ์ƒ
3.
completed : ์ •์ƒ์ ์œผ๋กœ ์ข…๋ฃŒ

onNext

Observable์„ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” Observer์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
onNext๋Š” Observable์˜ Stream์ด ๋Š๊ธฐ์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฒคํŠธ๋ฅผ ๊ณ„์† ๋ฐฉ์ถœ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

onCompleted

Observable์„ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” Observer์—๊ฒŒ ํ•ด๋‹น Observable์˜ Stream์ด ์„ฑ๊ณต์ ์œผ๋กœ ๋๋‚ฌ์Œ์„ ์•Œ๋ฆฝ๋‹ˆ๋‹ค.
onCompleted๋Š” Stream์„ ๋Š๊ณ  ์ด๋ฒคํŠธ๋ฅผ ์ข…๋ฃŒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

onError

Observable์„ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” Observer์—๊ฒŒ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Œ์„ ์•Œ๋ฆฌ๊ณ  Stream์„ ์ข…๋ฃŒ์‹œํ‚ต๋‹ˆ๋‹ค.
onError๋Š” ์ด๋ฒคํŠธ์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ์Œ์„ ์•Œ๊ณ  ์ค‘๊ฐ„์— Stream์„ ์ข…๋ฃŒ์‹œํ‚ต๋‹ˆ๋‹ค.
๊ทธ๋Ÿผ, ์ด๋ฒคํŠธ ๋ฐœํ–‰์˜ ์ฃผ์ฒด์ธ Observable์€ ์–ด๋–ป๊ฒŒ ์ƒ์„ฑ๋˜๋Š”๊ฑธ๊นŒ์š”?

ย Create Observable

Observable์„ ์ƒ์„ฑํ•˜๋Š” Operator๋ฅผ ๋งŒ๋‚˜๋ด…์‹œ๋‹ค.

just

ํ•˜๋‚˜์˜ ํ•ญ๋ชฉ์„ ๋ฐฉ์ถœํ•˜๋Š” Observable์„ ์ƒ์„ฑ
Observable.just([1, 2, 3]) .subscribe { event in print(event) } .disposed(by: disposedBag) /* next([1, 2, 3]) completed */
Swift
๋ณต์‚ฌ

from

๋ฐฐ์—ด์— ํฌํ•จ๋œ ์š”์†Œ๋ฅผ ํ•˜๋‚˜์”ฉ ์ˆœ์„œ๋Œ€๋กœ ๋ฐฉ์ถœํ•˜๋Š” Observable์„ ์ƒ์„ฑ
Observable.from([1, 2, 3]) .subscribe{ element in print(element) } .disposed(by: disposedBag) /* next(1) next(2) next(3) completed */
Swift
๋ณต์‚ฌ

create

์ง์ ‘์ ์ธ ์ฝ”๋“œ ๊ตฌํ˜„์„ ํ†ตํ•ด Observer ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Observable์„ ์ƒ์„ฑ
Observable<String>.create { observer in observer.onNext("A") observer.onCompleted() return Disposables.create() }.subscribe( onNext: { print($0) }, onError: { print($0) }, onCompleted: { print("Completed") }, onDisposed: { print("Disposed") } ).disposed(by: disposedBag) /* A Completed Disposed */
Swift
๋ณต์‚ฌ

deferred

Observer๊ฐ€ ๊ตฌ๋…ํ•˜๊ธฐ ์ „๊นŒ์ง€ Observable ์ƒ์„ฑ์„ ์ง€์—ฐํ–ˆ๋‹ค๊ฐ€, ๊ตฌ๋…์ด ์‹œ์ž‘๋˜๋ฉด Observer ๋ณ„๋กœ ์ƒˆ๋กœ์šด Observable์„ ์ƒ์„ฑ
.subscribe() ํ•˜๋Š” ์ˆœ๊ฐ„ .deferred()๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
let a = ["a", "a"] let b = ["b", "b"] var flag = true let observable: Observable<String> = Observable.deferred { flag = !flag if flag { return Observable.from(a) } else { return Observable.from(b) } } observable .subscribe { print($0) } .disposed(by: disposedBag) /* a a completed */ observable .subscribe { print($0) } .disposed(by: disposedBag) /* b b completed */
Swift
๋ณต์‚ฌ

range

์—ฐ์†๋œ ๋ฒ”์œ„์˜ ์ •์ˆ˜๋ฅผ ๋ฐœํ–‰ํ•˜๋Š” Observable์„ ์ƒ์„ฑ
start๋ถ€ํ„ฐ count ํฌ๊ธฐ ๋งŒํผ์˜ ๊ฐ’์„ ๊ฐ€์ง€๋Š” Observable์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
Observable.range(start: 1, count: 10) .subscribe { print($0) } .disposed(by: disposedBag) /* next(1) next(2) .. next(10) */
Swift
๋ณต์‚ฌ

generate

์„ค์ •ํ•œ ์กฐ๊ฑด์— ๋งž๋Š” ์ •์ˆ˜๋ฅผ ๋ฐœํ–‰ํ•˜๋Š” Observable์„ ์ƒ์„ฑ
โ€ข
initialState : ์‹œ์ž‘ ๊ฐ’ (๊ฐ€์žฅ ๋จผ์ € ๋ฐฉ์ถœ๋˜๋Š” ๊ฐ’)
โ€ข
condition : ์กฐ๊ฑด์ด true์ผ ๊ฒฝ์šฐ์—๋งŒ ์š”์†Œ๊ฐ€ ๋ฐฉ์ถœ๋จ (false์ผ ๊ฒฝ์šฐ completed)
โ€ข
iterate : ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚ค๊ฑฐ๋‚˜ ๊ฐ์†Œ์‹œํ‚ฌ ๊ฒฝ์šฐ์— ์‚ฌ์šฉ
Observable.generate(initialState: 0, condition: { $0 <= 10 }, iterate: { $0 + 2 }) .subscribe { print($0) } .disposed(by: disposedBag) /* next(0) next(2) next(4) next(6) next(8) next(10) completed */
Swift
๋ณต์‚ฌ

repeatElement

ํŠน์ • ์š”์†Œ๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋ฐฉ์ถœํ•˜๋Š” Observable์„ ์ƒ์„ฑ
Observable.repeatElement("A") //.take(7) // take Operater๋ฅผ ๋„ฃ์œผ๋ฉด 7๊ฐœ๋งŒ ๋ฐฉ์ถœํ•˜๊ณ  ์ข…๋ฃŒ .subscribe { print($0) } .disposed(by: disposedBag) /* next(A) next(A) next(A) ... */
Swift
๋ณต์‚ฌ

interval

์ง€์ •๋œ ์‹œ๊ฐ„์— ํ•œ ๋ฒˆ์”ฉ ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœ
Observable<Int>.interval(.seconds(3), scheduler: MainScheduler.instance) .take(10) .subscribe { print($0) } .disposed(by: disposedBag) // 3์ดˆ๋งˆ๋‹ค 0๋ถ€ํ„ฐ ์ˆซ์ž๊ฐ€ ์ฆ๊ฐ€ํ•˜๊ฒŒ ๋œ๋‹ค. /* next(0) next(1) ... next(9) completed */
Swift
๋ณต์‚ฌ

empty

ํ•ญ๋ชฉ์„ ๊ฐ€์ง€์ง€ ์•Š๋Š” Observable์„ ์ƒ์„ฑ
empty๋Š” .completed ์ด๋ฒคํŠธ๋งŒ ๋ฐฉ์ถœํ•ฉ๋‹ˆ๋‹ค. ํ•ญ๋ชฉ์€ ์—†์ง€๋งŒ ์ •์ƒ์ ์œผ๋กœ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.
Observable<Void>.empty() .subscribe { print($0) } .disposed(by: disposedBag) /* completed */
Swift
๋ณต์‚ฌ

never

ํ•ญ๋ชฉ์„ ๋ฐฉ์ถœํ•˜์ง€ ์•Š๊ณ  ์ข…๋ฃŒํ•˜์ง€ ์•Š๋Š” Observable์„ ์ƒ์„ฑ
Observable<Void>.never() .subscribe { print($0) } .disposed(by: disposedBag) // never๋Š” complete ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ.
Swift
๋ณต์‚ฌ

error

ํ•ญ๋ชฉ์„ ๋ฐฉ์ถœํ•˜์ง€ ์•Š๊ณ  ์˜ค๋ฅ˜๋กœ ์ข…๋ฃŒ๋˜๋Š” Observable์„ ์ƒ์„ฑ
Observable<Void>.error(NSError(domain: "400", code: 400)) .subscribe { print($0) } .disposed(by: disposedBag) /* error(Error Domain=400 Code=400 "(null)") */
Swift
๋ณต์‚ฌ

ย Subscribe Observable

Observable์„ ์ƒ์„ฑ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋งŒ๋“ค์–ด๋„ ๊ตฌ๋…์ด ๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด ์•„๋ฌด๋Ÿฐ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
๋‚ด๊ฐ€ ์ข‹์•„ํ•˜๋Š” ์œ ํŠœ๋ฒ„๋ฅผ ๊ตฌ๋…ํ•˜์ง€ ์•Š์œผ๋ฉด ์ƒˆ๋กœ์šด ์˜์ƒ์— ๋Œ€ํ•œ ์•„๋ฌด๋Ÿฐ ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์—†๋Š” ๊ฑฐ์ฒ˜๋Ÿผ์š”. ํ•˜์ง€๋งŒ, ํ•ด๋‹น ์œ ํŠœ๋ฒ„๋ฅผ ๊ตฌ๋…ํ•˜๋Š” ์ˆœ๊ฐ„๋ถ€ํ„ฐ๋Š” ์ƒˆ๋กœ์šด ์˜์ƒ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ตฌ๋…์€ โ€œsubscribeโ€๋งŒ ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
๋งŒ์•ฝ, ์ด๋Ÿฐ Observable์ด ์žˆ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค. Observable์€ ๋ฐฐ์—ด์—์„œ String ํƒ€์ž…์˜ ํ•ญ๋ชฉ์„ ํ•˜๋‚˜์”ฉ ๋นผ์„œ ์ „๋‹ฌํ•ด์ค๋‹ˆ๋‹ค.
let strObservable = Observable.from(["์•ˆ๋…•", "ํ•˜์„ธ์š”", "๋ฐ˜๊ฐ‘", "์Šต๋‹ˆ๋‹ค"])
Swift
๋ณต์‚ฌ
ํ•˜์ง€๋งŒ, ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๊ณ  ์‹ถ์–ดํ•˜๋Š” Observer๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ฌด๋Ÿฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ์ˆ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋ฉด, ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ๋” ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ๋…ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณผ๊ฒŒ์š”.
strObservable.subscribe { print($0) }
Swift
๋ณต์‚ฌ
์ด๋ ‡๊ฒŒ ํ•˜๋ฉด, Observable์ด ๋ฐฉ์ถœํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ Observer๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ๊ฐ€ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.
/* next(์•ˆ๋…•) next(ํ•˜์„ธ์š”) next(๋ฐ˜๊ฐ‘) next(์Šต๋‹ˆ๋‹ค) completed */
Swift
๋ณต์‚ฌ
ํ•˜์ง€๋งŒ, ๊ตฌ๋…ํ•˜๊ณ  ๋์ด ์•„๋‹™๋‹ˆ๋‹ค.
๊ตฌ๋…ํ•˜๊ณ  ๋‚˜์„œ Observable๊ณผ ๊ด€๋ จ๋œ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ทธ๋Œ€๋กœ ๋‚จ๊ฒจ๋‘”๋‹ค๋ฉด ๋‚˜์ค‘์— ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋ฉด, ๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‚˜์š”?
subscribe ์—๋Š” next, error, completed๋ง๊ณ ๋„ disposed๋ผ๋Š” ์˜ต์…”๋„ ํƒ€์ž… ํด๋กœ์ € ์ธ์ž๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
disposed๋Š” Observable๊ณผ ๊ด€๋ จ๋œ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๊ฐ€ ์ œ๊ฑฐ๋œ ๋‹ค์Œ์— ํ˜ธ์ถœ๋˜๋Š” ํด๋กœ์ €์ž…๋‹ˆ๋‹ค.
Observable ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•  ๋•Œ์— ์‹คํ–‰์‹œํ‚ค๊ณ  ์‹ถ์€ ์ฝ”๋“œ๋Š” disposed ๋ถ€๋ถ„์— ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
strObservable.subscribe(onNext: { print($0) }, onError: {_ in // Observable error }, onCompleted: { // Observable completed }, onDisposed: { // ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ ์‹œ์— ํ˜ธ์ถœํ•˜๊ณ  ์‹ถ์€ ์ฝ”๋“œ })
Swift
๋ณต์‚ฌ
onError๋‚˜ onCompleted๋˜์–ด์„œ Stream์ด ๋๋‚˜๋ฉด onDisposed๊ฐ€ ๋ถˆ๋ฆฌ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
error, completed ์ดํ›„์— ๋ฆฌ์†Œ์Šค ๊ด€๋ฆฌํ•ด์ค„ ํ•„์š”์—†์ด ์ •์ƒ์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•ด์ œ๋˜์ง€๋งŒ ๊ณต์‹ ๊ฐ€์ด๋“œ๋ผ์ธ์— ๋”ฐ๋ฅด๋ฉด ์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋„ ์ˆ˜๋™์ ์œผ๋กœ ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œํ•ด์ค„ ๊ฒƒ์„ ๊ถŒ๊ณ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ˆ˜๋™์ ์ธ ๋ฆฌ์†Œ์Šค ํ•ด์ œ๋ฅผ ์œ„ํ•ด์„œ disposed๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
Observable.from([1, 2, 3]) .subscribe{ element in print(element) } .disposed(by: disposedBag)
Swift
๋ณต์‚ฌ
disposed ๋ฉ”์„œ๋“œ์—์„œ ์ธ์ˆ˜๋กœ ์‚ฌ์šฉ๋˜๋Š” disposedBag์€ Disposable ํƒ€์ž…์„ ๋ชจ๋‘ ๋ชจ์•„์„œ ํ•œ๊บผ๋ฒˆ์— ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, Observable์„ ์ƒ์„ฑํ•˜๊ณ  ๊ตฌ๋…ํ•œ ๋‹ค์Œ์— ๋ฐ”๋กœ dispose ์‹œํ‚ค๋ฉด ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿผ, ๊ตฌ๋…ํ•˜๊ณ  ๋‚˜์„œ ๋ฐ”๋กœ dispose๋˜๋Š”๊ฑด ์•„๋‹Œ๊ฐ€์š”?
์•„๋‹™๋‹ˆ๋‹ค. disposeBag์— ๋‹ด๊ฒจ์žˆ๋Š” disposable์€ disposeBag์ด ํ•ด์ œ๋  ๋•Œ ํ•จ๊ป˜ ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค.

ย Trait

Trait๋Š” ์ผ๋ฐ˜์ ์ธ Observable๋ณด๋‹ค ์ข์€ ๋ฒ”์œ„์˜ Observable์ž…๋‹ˆ๋‹ค.

Single

๋‹จ์ผ ํ•ญ๋ชฉ์ด๋‚˜ ์˜ค๋ฅ˜ ๋ฐฉ์ถœ
Single์€ Observable์˜ ํ•œ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค. ํŠน์ดํ•œ ์ ์ด ์žˆ๋‹ค๋ฉด ํ•œ ๊ฐ€์ง€ ๊ฐ’์ด๋‚˜ ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ถœํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.
๊ฐ’์ด success ๋˜๋Š” error ํ˜•ํƒœ๋กœ ๋ฐฉ์ถœ๋ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ, โ€œ์„ฑ๊ณต์ด๋ƒโ€, โ€œ์‹คํŒจ๋ƒโ€๋ฅผ ๋”ฐ์ง€๋Š” ์ผ์— ์ ํ•ฉํ•œ Observable ์ž…๋‹ˆ๋‹ค.
func getRepo(_ repo: String) -> Single<[String: Any]> { return Single<[String: Any]>.create { single in let task = URLSession.shared.dataTask(with: URL(string: "https://api.github.com/repos/\(repo)")!) { data, _, error in if let error = error { single(.error(error)) return } guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves), let result = json as? [String: Any] else { single(.error(DataError.cantParseJSON)) return } single(.success(result)) } task.resume() return Disposables.create { task.cancel() } } } getRepo("ReactiveX/RxSwift") .subscribe(onSuccess: { json in print("JSON: ", json) }, onError: { error in print("Error: ", error) }) .disposed(by: disposeBag)
Swift
๋ณต์‚ฌ
Observable์€ completed ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, Single์€ completed ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ฆ‰, Single์˜ ์ด๋ฒคํŠธ์ธ success ์ž์ฒด๊ฐ€ next, completed ๋‘ ๊ฐœ์˜ ์„ฑ๊ฒฉ์„ ๋‹ค ํฌํ•จํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, completed ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœํ–‰๋œ ์ƒํƒœ์—์„œ ์ด์ „์— next ์ด๋ฒคํŠธ๊ฐ€ ๋“ค์–ด์˜ค์ง€ ์•Š์œผ๋ฉด ์—๋Ÿฌ๋ฅผ ์ „๋‹ฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
case .completed: if self.seenValue { self.forwardOn(.completed) } else { self.forwardOn(.error(RxError.noElements)) // ์—๋Ÿฌ ๋ฐœ์ƒ } self.dispose() }
Swift
๋ณต์‚ฌ
Observable์€ asSingle()์ด๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ Observable ํƒ€์ž…์„ Single ํƒ€์ž…์œผ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ƒํ™ฉ์—์„œ ์ด์ „๊ณผ ๋™์ผํ•˜๊ฒŒ completed ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœํ–‰๋œ๋‹ค๋ฉด ๊ทธ ์ด์ „์— next ์ด๋ฒคํŠธ๊ฐ€ ๋“ค์–ด์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด, ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
case .completed: if let element = self.element { self.forwardOn(element) self.forwardOn(.completed) } else { self.forwardOn(.error(RxError.noElements)) } self.dispose() }
Swift
๋ณต์‚ฌ
Single์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ Single๋กœ ์‹œ์ž‘ํ•˜๋„๋ก ํ•˜๊ณ , Observable๋กœ ์‹œ์ž‘ํ•œ ๊ฒฝ์šฐ์—๋Š” ๋ถˆํ•„์š”ํ•œ ์—๋Ÿฌ๋ฅผ ๋ฐœํ–‰ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๊ธ‰์  ์ค‘๊ฐ„์— Single๋กœ ํƒ€์ž… ๋ณ€๊ฒฝ์„ ํ•˜๋Š” ์ผ์€ ์ง€์–‘ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

Completable

Single๊ณผ ๊ธฐ๋Šฅ์ด ์œ ์‚ฌํ•˜์ง€๋งŒ, value๊ฐ’์„ ๋ฐฉ์ถœํ•˜์ง€ ์•Š์Œ
์–ด๋Š ํ•ญ๋ชฉ๋„ ๋ฐฉ์ถœํ•˜์ง€ ์•Š๊ณ , ์—๋Ÿฌ๋‚˜ ์™„๋ฃŒ๋งŒ ๊ฐ€๋Šฅํ•œ Observable์˜ ๋ณ€ํ˜•์ž…๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ, ์ผ์ด ์ œ๋Œ€๋กœ ๋๋Š”์ง€๋งŒ ๊ฒ€ํ† ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹์Šต๋‹ˆ๋‹ค.
Completable๋Š” Single, Maybe์™€ ๋‹ค๋ฅด๊ฒŒ Observable์„ Completable๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
func cacheLocally() -> Completable { return Completable.create { completable in guard success else { completable(.error(CacheError.failedCaching)) return Disposables.create {} } completable(.completed) return Disposables.create {} } } cacheLocally() .subscribe { completable in switch completable { case .completed: print("Completed with no error") case .error(let error): print("Completed with an error: \(error.localizedDescription)") } } .disposed(by: disposeBag)
Swift
๋ณต์‚ฌ

Maybe

Single๊ณผ Completable์„ ์„ž์–ด ๋†“์€ ํ˜•ํƒœ
Maybe๋Š” .success(value), .completed, .error๋ฅผ ๋ฐฉ์ถœํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์Šค์˜ ์„ฑ๊ณต, ์‹คํŒจ ์—ฌ๋ถ€์™€ ๋”๋ถˆ์–ด ์ถœ๋ ฅ๋œ ๊ฐ’๋„ ๋ฐฉ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
func generateString() -> Maybe<String> { return Maybe<String>.create { maybe in maybe(.success("RxSwift")) maybe(.completed) maybe(.error(error)) return Disposables.create {} } } generateString() .subscribe(onSuccess: { element in print("Completed with element \(element)") }, onError: { error in print("Completed with an error \(error.localizedDescription)") }, onCompleted: { print("Completed with no element") }) .disposed(by: disposeBag)
Swift
๋ณต์‚ฌ