RxSwift) Error Handling Operators

Havi·2021년 3월 24일
0

RxSwift 기초

목록 보기
11/14

참고 1 <- 추천
참고 2
참고 3
참고 4

RxSwift에서 에러를 관리하는 방법

RxSwift에서 에러를 핸들링하는 방법으로는 크게 3가지가 있다.

  1. catch : 특정 값으로 Error 복구
  2. retry : 재시도 하기
  3. materialize / dematerialize : Sequence 를 제어해서 처리

Catch Operator

공식 문서 - catch

Swift의 do try catch문과 유사하게 동작한다.

에러가 발생 시 특정 값을 return하여 onError를 부르지 않고 onComplete로 시퀀스를 종료한다.

설명

마블

Catch

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

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 Operator

공식 문서 - retry

설명

마블

Retry

성공할 때 까지 계속 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>
}

예제

RetryWhen

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))
    }

예제

Materialize

구현체와 마블은 이전글 참조

예제

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
            */
profile
iOS Developer

0개의 댓글