RxSwift 를 사용하면서 흔히 발생하는 Error 를 어떤 Operator 를 사용하여 Handling 하는지에 대하여 알아 보려고 합니다.
let observable = Observable<Int>
.create { observer -> Disposable in
observer.onNext(1)
observer.onNext(2)
observer.onNext(3)
observer.onError(NSError(domain: "", code: 100, userInfo: nil))
observer.onError(NSError(domain: "", code: 200, userInfo: nil))
return Disposables.create { }
}
observable
.catchError { .just(($0 as NSError).code) }
.subscribe { print($0) }
.disposed(by: disposeBag)
/* Prints:
next(1)
next(2)
next(3)
next(100)
completed
*/
1, 2, 3 이 정상적으로 출력되는걸 확인할 수 있다.
code: 100 Error가 발생하고 catchError에서 Error 가 .just(100)로 바뀌어 에러코드가 print 되고 complete 된걸 확인할 수 있습니다.
let observable = Observable<Int>
.create { observer -> Disposable in
observer.onNext(1)
observer.onNext(2)
observer.onNext(3)
observer.onError(NSError(domain: "", code: 100, userInfo: nil))
observer.onError(NSError(domain: "", code: 200, userInfo: nil))
return Disposables.create { }
}
observable
.catchErrorJustReturn(999)
.subscribe { print($0) }
.disposed(by: disposeBag)
/* Prints:
next(1)
next(2)
next(3)
next(999)
completed
*/
말 그대로 에러가 발생 했을 때 다시 시도할 수 있게 해준다.
에러가 발생했을 때 Observable 을 다시 시도한다(Observable 내의 전체작업을 반복)
아래의 사진처럼 네트워킹 요청에서 에러가 발생할 경우 retry 를 사용해 다시 시도할 수 있다.
일반적인 재시도에 사용하는 연산자이다. 에러가 발생했을 때 성공할 때까지 Observable을 다시 시도한다.
아래의 코드는 네트워킹을 통해 repositories를 가져오는 코드이다. 인터넷 연결을 끊고 reload를 하면 콘솔에 실패 메세지가 계속 찍히는 것을 확인할 수 있다.
let reloadPublisher = PublishSubject<Void>()
reloadPublisher
.flatMap {
Api.getRepositories()
.retry()
}
let reloadPublisher = PublishSubject<Void>()
reloadPublisher
.flatMap {
Api.getRepositories()
.retry(3)
}
let observable = Observable<Int>
.create { observer -> Disposable in
observer.onNext(1)
observer.onNext(2)
observer.onNext(3)
observer.onError(NSError(domain: "", code: 100, userInfo: nil))
observer.onError(NSError(domain: "", code: 200, userInfo: nil))
return Disposables.create { }
}
observable
.retry(2)
.subscribe { print($0) }
.disposed(by: disposeBag)
/* Prints:
next(1)
next(2)
next(3)
next(1)
next(2)
next(3)
error(Error Domain= Code=100 "(null)")
*/
let observable = Observable<Int>
.create { observer -> Disposable in
observer.onNext(1)
observer.onNext(2)
observer.onNext(3)
observer.onError(NSError(domain: "", code: 100, userInfo: nil))
observer.onError(NSError(domain: "", code: 200, userInfo: nil))
return Disposables.create { }
}
observable
.retry { err -> Observable<Int> in
return .timer(3, scheduler: MainScheduler.instance)
}
.subscribe { print($0) }
.disposed(by: disposeBag)
/* Prints:
next(1)
next(2)
next(3)
(3 seconds)
next(1)
next(2)
next(3)
completed
*/
Sequence 를 Event Sequence로 변환한다.
Event Sequence 를 다시 Sequence로 변환한다.
let observable = Observable<Int>
.create { observer -> Disposable in
observer.onNext(1)
observer.onNext(2)
observer.onNext(3)
observer.onError(NSError(domain: "", code: 100, userInfo: nil))
observer.onError(NSError(domain: "", code: 200, userInfo: nil))
return Disposables.create { }
}
observable
.materialize()
.map { event -> Event<Int> in
switch event {
case .error:
return .next(999)
default:
return event
}
}
.dematerialize()
.subscribe { event in
print(event)
}
.disposed(by: disposeBag)
/* Prints
next(1)
next(2)
next(3)
next(999)
completed
*/