RxSwift에서 에러를 핸들링하는 방법으로는 크게 3가지가 있다.
Swift의 do try catch문과 유사하게 동작한다.
에러가 발생 시 특정 값을 return하여 onError를 부르지 않고 onComplete로 시퀀스를 종료한다.
catchError는 deprecated 되었다. catch(_ handler:)를 사용하자.
1,2,3이 출력된 후 notFoundError가 떨어져서 rawValue를 출력한 뒤 onComplete가 나온다.
Continues an observable sequence that is terminated by an error with the observable sequence produced by the handler.
- seealso: [catch operator on reactivex.io](http://reactivex.io/documentation/operators/catch.html)
- parameter handler: Error handler function, producing another observable sequence.
- returns: An observable sequence containing the source sequence's elements, followed by the elements produced by the handler's resulting observable sequence in case an error occurred.
*/
public func `catch`(_ handler: @escaping (Error) throws -> RxSwift.Observable<Self.Element>) -> RxSwift.Observable<Self.Element>
enum TestError: Int, Error {
case notFound = 200
case noInternet = -1
}
let observable = Observable<Int>
.create { observer -> Disposable in
observer.onNext(1)
observer.onNext(2)
observer.onNext(3)
observer.onError(TestError.notFound)
observer.onError(TestError.noInternet)
return Disposables.create { }
}
observable
.catch { err -> Observable<Int> in
let testError = err as? TestError
return .just(testError?.rawValue ?? -1)
}
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
/*
1
2
3
200
*/
CatchErrorJustReturn는 deprecated 되었다. catchAndReturn를 쓰자.
어떤 가공이 들어가지 않고 바로 element을 방출할 때 사용한다.
에러 코드를 구분하지 않고 에러다 아니다를 구분하기 위해 -1을 던졌다.
/**
Continues an observable sequence that is terminated by an error with a single element.
- seealso: [catch operator on reactivex.io](http://reactivex.io/documentation/operators/catch.html)
- parameter element: Last element in an observable sequence in case error occurs.
- returns: An observable sequence containing the source sequence's elements, followed by the `element` in case an error occurred.
*/
public func catchAndReturn(_ element: Self.Element) -> RxSwift.Observable<Self.Element>
observable
.catchAndReturn(-1)
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
/*
1
2
3
-1
*/
성공할 때 까지 계속 retry한다.
maxCount는 최대 retry횟수를 지정해준다.
여기서 주의할 점은 처음 시도 횟수도 포함된다.
즉 3으로 설정할 경우, 최초 시도에서 error가 떨어졌을 때 2번만 retry하게 된다.
extension ObservableType {
/**
Repeats the source observable sequence until it successfully terminates.
**This could potentially create an infinite sequence.**
- seealso: [retry operator on reactivex.io](http://reactivex.io/documentation/operators/retry.html)
- returns: Observable sequence to repeat until it successfully terminates.
*/
public func retry() -> RxSwift.Observable<Self.Element>
/**
Repeats the source observable sequence the specified number of times in case of an error or until it successfully terminates.
If you encounter an error and want it to retry once, then you must use `retry(2)`
- seealso: [retry operator on reactivex.io](http://reactivex.io/documentation/operators/retry.html)
- parameter maxAttemptCount: Maximum number of times to repeat the sequence.
- returns: An observable sequence producing the elements of the given sequence repeatedly until it terminates successfully.
*/
public func retry(_ maxAttemptCount: Int) -> RxSwift.Observable<Self.Element>
}
Error가 떨어졌을 때 error를 가공해 observerbleType을 반환한다.
즉 다음 예제처럼 retry시점을 조작하거나 값을 변경할 수 있다.
/**
Repeats the source observable sequence on error when the notifier emits a next value.
If the source observable errors and the notifier completes, it will complete the source sequence.
- seealso: [retry operator on reactivex.io](http://reactivex.io/documentation/operators/retry.html)
- parameter notificationHandler: A handler that is passed an observable sequence of errors raised by the source observable and returns and observable that either continues, completes or errors. This behavior is then applied to the source observable.
- returns: An observable sequence producing the elements of the given sequence repeatedly until it terminates successfully or is notified to error or complete.
*/
public func retry<TriggerObservable: ObservableType, Error: Swift.Error>(when notificationHandler: @escaping (Observable<Error>) -> TriggerObservable)
-> PrimitiveSequence<Trait, Element> {
PrimitiveSequence(raw: self.source.retry(when: notificationHandler))
}
구현체와 마블은 이전글 참조
observable
.materialize()
.map { event -> Event<Int> in
switch event {
case .error:
return .next(-1)
default:
return event
}
}
.dematerialize()
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
/*
1
2
3
-1
*/