Observable -> Subscriber ๋ก ErrorEvent๊ฐ ์ ๋ฌ๋๋ฉด, ๊ตฌ๋
์ด ์ข
๋ฃ๋๊ณ ๋ ์ด์ ์ด๋ฒคํธ๋ฅผ ์ ๋ฌ๋ฐ์ง ๋ชปํ๊ฒ ๋๋ค. ๊ทธ๋ ๊ฒ๋๋ฉด ๋ ์ด์ ์๋ก์ด ์ด๋ฒคํธ์ ๋ํด์ ํธ๋ค๋งํ ์ ์๊ฒ๋๋ค.
์ผ๋ฐ์ ์ธ์ํฉ์์ Observable์ Network๋ฅผ ์์ฒญํ๊ณ , Subscriber๋ UI๋ฅผ ์
๋ฐ์ดํธํ๋ค. ์ด๋ ErrorEvent๊ฐ ๋ฐ์ํ๋ฉด ๊ตฌ๋
์ด ์ข
๋ฃ๋์ด ๋ ์ด์ UI๋ฅผ ์
๋ฐ์ดํธ ํ์ง ๋ชปํ๊ฒ๋๋ค.
์ด๋ฌํ ๋ฌธ์ ๋ฅผ catch
ํน์ retry
๋ฅผ ํตํด์ ํด๊ฒฐํ ์ ์๋ค.
Catch (Operator)
CatchError๋ฅผ ์ฌ์ฉํ๋ฉด Next, Completed ์ด๋ฒคํธ๋ ํ์๋๋ก ๊ตฌ๋
์์๊ฒ ์ ๋ฌํ๋ค. ํ์ง๋ง ErrorEvent๊ฐ ๋ฐ์ํ๋ฉด ์๋ก์ด Observable์ ์์ฑํ์ฌ ๊ตฌ๋
์์๊ฒ ์ ๋ฌํด์ฃผ๊ฑฐ๋, ๊ธฐ๋ณธ๊ฐ์ ์ ๋ฌํ์ฌ UI ์
๋ฐ์ดํธ๊ฐ ๋์ด์ง์ง ์๋๋ก ํ ์ ์๋ ์ฐ์ฐ์์ด๋ค.
enum TError: Error{
case testError
}
let bag = DisposeBag()
let subject = PublishSubject<Int>()
let recovery = PublishSubject<Int>()
subject
.catch({ error in
recovery // ์๋ฌ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์๋, ์๋ก์ด ์ต์ ๋ฒ๋ธ์ ๋ฐํํด์ค๋ค. (์๋ ์ต์ ๋ฒ๋ธ๊ณผ ์๋ก์ด ์ต์ ๋ฒ๋ธ์ด ๊ต์ฒด๋๋ค.)
})
.subscribe { print($0) }
.disposed(by: bag)
subject.onNext(1)
subject.onError(TError.testError) // ์ด์์ ์์ ๊ตฌ๋
์ด ์ข
๋ฃ๋๋ค.
subject.onNext(2) // ๊ตฌ๋
์ด ์ข
๋ฃ๋์๊ธฐ ๋๋ฌธ์ ๋ฐ์ ์์
recovery.onNext(188) // catch๋ก ๋ฐ์ ์๋ก์ด observable
catchAndReturn
let bag = DisposeBag()
enum MyError: Error {
case error
}
let subject = PublishSubject<Int>()
subject
.catchAndReturn(-199)
.subscribe { print($0) }
.disposed(by: bag)
subject.onNext(100)
subject.onError(MyError.error) // ์ง์ ํด๋ ๊ธฐ๋ณธ๊ฐ์ด return ๋๊ณ completed ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ๋ค.
subject.onNext(100) // ๋ ์ด์ ์ด๋ฒคํธ๊ฐ ๋ฐฉ์ถ๋์ง ์๋๋ค.
Retry
CatchError
์ ๋ง์ฐฌ๊ฐ์ง๋ก Next, Completed ์ด๋ฒคํธ์์๋ ๋ฌ๋ผ์ง๋๊ฒ ์์ง๋ง, ErrorEvent๊ฐ ๋ฐ์ํ๋ฉด Subscriber์๊ฒ ์ ๋ฌํ์ง ์๊ณ ๋ค์ ์คํจํ๋์์
์(์ฃผ๋ก network ์์
) ์๋ํ๊ฒ๋๋ค. ์ด๋ ์ฌ์๋ ํ์๋ ์ ํ์ด ๊ฐ๋ฅํ๋ค.
let bag = DisposeBag()
enum MyError: Error {
case error
}
var attempts = 1
let source = Observable<Int>.create { observer in
let currentAttempts = attempts
print("#\(currentAttempts) START")
if attempts < 3 {
observer.onError(MyError.error)
attempts += 1 // 3์ด ๋์ด๊ฐ๋๊น์ง ์ฌ์๋๋ฅผ ํ๋ฉด ์๋์ onNext์ด๋ฒคํธ๊ฐ ์ ๋ฌ๋๊ฒ๋๋ค.
}
observer.onNext(1)
observer.onNext(2)
observer.onCompleted()
return Disposables.create {
print("#\(currentAttempts) END")
}
}
source
.retry(5)
.subscribe { print($0) }
.disposed(by: bag)
retry(When:)
๊ธฐ๋ณธ์ ์ผ๋ก ErrorEvnet๊ฐ ๋ฐ์ํ๋ฉด retry๋ฅผ ์๋ํ๋ค๋๊ฑด ๊ฐ์ง๋ง, retry๋ฅผ ๋ฐ๋กํ๋๊ฒ ์๋๋ผ ์ธ์ ํ ์ง ์์ ์์ ํด์ค ์ ์๋ค.
let bag = DisposeBag()
enum MyError: Error {
case error
}
var attempts = 1
let source = Observable<Int>.create { observer in
let currentAttempts = attempts
print("START #\(currentAttempts)")
if attempts < 3 {
observer.onError(MyError.error)
attempts += 1
}
observer.onNext(1)
observer.onNext(2)
observer.onCompleted()
return Disposables.create {
print("END #\(currentAttempts)")
}
}
let trigger = PublishSubject<Void>()
source
.retry(when: { _ in
trigger
})
.subscribe { print($0) }
.disposed(by: bag)
trigger.on(.next(())) // ์ด ์์ ์์ retry๋ฅผ ์๋ํ๊ฒ๋๋ค.