본문 바로가기
RxSwift

[RxSwift] Operators - 오류 처리(5)

by 고고 2021. 11. 20.

Observable이 던진 오류를 복구할 수 있도록 도와주는 연산자들 - Catch, Retry

안녕하세요 ◠‿◠ 고고입니다.

 

1. Catch

  • Catch — 오류를 무시하고 배출되는 항목들을 계속 진행시켜 'onError'로부터 전달된 오류를 복구한다

구현부

public func `catch`(_ handler: @escaping (Swift.Error) throws -> Observable<Element>)
        -> Observable<Element> {
        Catch(source: self.asObservable(), handler: handler)
    }

예시

let source = Observable<Int>.create { observer in
	for count in 1...3 {
		observer.on(.next(count))
	}
	let error = NSError(domain: "dummyError", code: 0, userInfo: nil)
	observer.on(.error(error))
	return Disposables.create {
		print("disposed")
	}
}

source.catch { error -> Observable<String> in
	return Observable.just("Here is an error.")
    }
    .subscribe{ print($0) }
        
// 1
// 2
// 3
// Here is an error.
// disposed

 

- catchAndReturn (구 catchErrorJustReturn)

  • catchAndReturn은 위와 같이 error가 발생했을때 설정해둔 단일 이벤트를 전달하도록 하는 연산자이다.
  • subscribe에서 에러를 감지 하는 것이 아닌, Observable에서 에러에 대한 기본 이벤트를 설정하는 부분에 주목하자.

구현부

public func catchAndReturn(_ element: Element)
        -> Observable<Element> {
        Catch(source: self.asObservable(), handler: { _ in Observable.just(element) })
    }

예시

let source = Observable<Int>.create { observer in
	for count in 1...3 {
		observer.on(.next(count))
	}
	let error = NSError(domain: "dummyError", code: 0, userInfo: nil)
	observer.on(.error(error))
	return Disposables.create {
		print("disposed")
	}
}.catchAndReturn(-1)

source
    .subscribe{ print($0) }
        
// 1
// 2
// 3
// -1
// disposed

 

 

2. Retry

  • Retry — 만약 소스 Observable이 'onError' 알림을 보낼 경우, 오류 없이 실행이 완료되기를 기대하며 재구독을 시도한다

구현부

public func retry() -> Observable<Element> {
        CatchSequence(sources: InfiniteSequence(repeatedValue: self.asObservable()))
    }

예시

let source = Observable<Int>.create { observer in
	for count in 1...3 {
		observer.on(.next(count))
	}
	let error = NSError(domain: "dummyError", code: 0, userInfo: nil)
	observer.on(.error(error))
	return Disposables.create {
		print("disposed")
	}
}

source
    .subscribe{ print($0) }
        
// 1
// 2
// 3
// 1
// 2
// 3
// ...

 

- retryWhen

  • 재시도 하는 시점을 지정할 수 있고, 한번만 수행한다.

구현부

public func retry<TriggerObservable: ObservableType>(when notificationHandler: @escaping (Observable<Swift.Error>) -> TriggerObservable)
        -> Observable<Element> {
        RetryWhenSequence(sources: InfiniteSequence(repeatedValue: self.asObservable()), notificationHandler: notificationHandler)
    }

예시

let source = Observable<Int>.create { observer in
	for count in 1...3 {
		observer.on(.next(count))
	}
	let error = NSError(domain: "dummyError", code: 0, userInfo: nil)
	observer.on(.error(error))
	return Disposables.create {
		print("disposed")
	}
}

source
	.retry(when: { err -> Observable<Int> in
		return .timer(3, scheduler: MainScheduler.instance)
	})
    .subscribe{ print($0) }
        
// 1
// 2
// 3
// (3초 후...)
// 1
// 2
// 3
// completed

 

 

+)

3. Materialize, Dematerialize

  • RxSwift 에서 쓰이는 Event Sequence를 제어할 수 있게 해준다.
  • 보통 Materialize / Dematerialize 는 함께 사용한다.
  • Observable을 분해할 수 있기 때문에 신중하게 사용해야 한다.

Materialize

  • Sequence 를 Event<Element> Sequence로 변환한다.
 

구현부

public func materialize() -> Observable<Event<Element>> {
        Materialize(source: self.asObservable())
    }

Dematerialize

  • Event<Element> Sequence 를 다시 Sequence로 변환한다.

구현부

public func dematerialize() -> Observable<Element.Element> {
        Dematerialize(source: self.asObservable())
    }

예시

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 { print($0) }

// next(1)
// next(2)
// next(3)
// next(999)
// completed

 

 

참고 : https://okanghoon.medium.com/rxswift-5-error-handling-example-9f15176d11fc

 

RxSwift #5 — Error Handling & Example

이번에는 RxSwift에서 어떻게 Error Handling 을 하는지 앱에서 흔히 발생하는 에러 예제들을 통해 알아보려고 한다.

okanghoon.medium.com

 

 

출처 : http://reactivex.io/documentation/ko/operators.html

 

ReactiveX - Operators

연산자 소개 ReactiveX를 지원하는 언어 별 구현체들은 다양한 연산자들을 제공하는데, 이 중에는 공통적으로 제공되는 연산자도 있지만 반대로 특정 구현체에서만 제공하는 연산자들도 존재한다

reactivex.io

 

 

'RxSwift' 카테고리의 다른 글

[RxSwift] Operators - 조건과 Boolean(7)  (0) 2021.11.29
[RxSwift] Operators - 유틸리티(6)  (0) 2021.11.29
[RxSwift] Operators - 결합(4)  (0) 2021.11.20
[RxSwift] Operators - 필터링(3)  (0) 2021.11.19
[RxSwift] Operators - 변환(2)  (0) 2021.11.19

댓글