Tunko Development Diary

RxSwift) Error Handling (retry, retry(when:)) 본문

Development/RxSwift

RxSwift) Error Handling (retry, retry(when:))

Tunko 2022. 6. 10. 13:42

retry

retry연산자는 옵저버블에서 에러가 발생하면 현재 시퀀스를 중단하고 다시 새로운 구독을 시작합니다.

새롭게 구독하는것이므로 기존에 있던 next이벤트들은 소멸되고 다시 시작합니다.

 

retry 연산자 함수 원형

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

public func retry(_ maxAttemptCount: Int)
    -> Observable<Element> {
    CatchSequence(sources: Swift.repeatElement(self.asObservable(), count: maxAttemptCount))
}

함수 원형을 보시면 두가지 케이스가 있습니다.

retry 연산자는 파라미터가 전달되지 않을시 계속 재시도를 하게 됩니다.

즉, 계속 에러가 나오게 되면 무한루프에 빠지게 되니 매우 위험합니다.

 

따라서 안전장치인 retry(_ maxAttemptCount: Int) 형태의 메소드도 구현되었습니다.

재시도 횟수에 제한을 걸어주는 retay메소드 입니다.

 

retry연산자는 Error가 발생하면 즉시 재시도를 합니다. 재시도 하는 시점을 컨트롤 할 수 없습니다.

에러가 발생하고 원하는 시점에 재시도를 하기위해선 retay연산자가 아닌 retry(when:) 연산자를 사용해야 합니다.

우선 retry 연산자를 보겠습니다.

let disposeBag = DisposeBag()

enum TunkoError: Error {
    case error
}

var 재시도횟수 = 1

let source = Observable<Int>.create { observer in
    let 현재재시도횟수 = 재시도횟수
    print("현재재시도횟수\\(현재재시도횟수) 시작")
    
    if 재시도횟수 < 5 {
        observer.onError(TunkoError.error)
        재시도횟수 += 1
    }
    
    observer.onNext(1)
    observer.onNext(2)
    observer.onCompleted()
    
    return Disposables.create {
        print("#\\(현재재시도횟수) 끝")
    }
}

source
    .retry()
    .subscribe { print($0) }
    .disposed(by: disposeBag)

출력

현재재시도횟수 [1] 시작
현재재시도횟수 [1] 끝
현재재시도횟수 [2] 시작
현재재시도횟수 [2] 끝
현재재시도횟수 [3] 시작
현재재시도횟수 [3] 끝
현재재시도횟수 [4] 시작
현재재시도횟수 [4] 끝
현재재시도횟수 [5] 시작
next(1)
next(2)
completed
현재재시도횟수 [5] 끝

retry(when: )

retryWhen은 클로저를 파라미터로 받아서 트리거 옵저버블을 리턴합니다. 그리고 리턴된 옵저버블에서 next이벤트가 발생하면 구독을 재시도하게 됩니다.

let disposeBag = DisposeBag()

enum TunkoError: Error {
    case error
}

var 재시도횟수 = 1

let source = Observable<Int>.create { observer in
    let 현재재시도횟수 = 재시도횟수
    print("현재재시도횟수 [\\(현재재시도횟수)] 시작")
    
    if 재시도횟수 < 5 {
        observer.onError(TunkoError.error)
        재시도횟수 += 1
    }
    
    observer.onNext(1)
    observer.onNext(2)
    observer.onCompleted()
    
    return Disposables.create {
        print("현재재시도횟수 [\\(현재재시도횟수)] 끝")
    }
}

let trigger = PublishSubject<Void>()
source
    .retry { _ in trigger}
    .subscribe { print($0) }
    .disposed(by: disposeBag)

print("--------------지금 재시도---------------")
trigger.onNext(())
trigger.onNext(())
trigger.onNext(())
trigger.onNext(())

출력

현재재시도횟수 [1] 시작
현재재시도횟수 [1] 끝
--------------지금 재시도---------------
현재재시도횟수 [2] 시작
현재재시도횟수 [2] 끝
현재재시도횟수 [3] 시작
현재재시도횟수 [3] 끝
현재재시도횟수 [4] 시작
현재재시도횟수 [4] 끝
현재재시도횟수 [5] 시작
next(1)
next(2)
completed
현재재시도횟수 [5] 끝
반응형

'Development > RxSwift' 카테고리의 다른 글

RxSwift) RxCocoa Binding  (0) 2022.06.12
RxSwift) RxCocoa 란?  (0) 2022.06.12
RxSwift) Error Handling (catch, catchAndReturn)  (0) 2022.06.10
RxSwift) Scheduler  (0) 2022.06.09
RxSwift) sharing Subscription Operator (share)  (0) 2022.06.08
Comments