포스트

RxSwift 연산자 정리 ⑥ - Error Handling

Error Handling 연산자

RxSwift에서 옵저버블Error 항목을 방출할 경우, 옵저버는 더 이상 옵저버블로부터 항목을 전달받지 못합니다. 그래서 이를 처리해줄 수 있는 여러 예외 연산자가 존재합니다. Error Handling 연산자는 옵저버블Error 항목을 방출하면 다른 옵저버블의 항목이나 기본 값을 방출하게 하거나, 정해진 횟수만큼 재시도(retry)를 하게 만들 수 있습니다. 대표적인 연산자로 catch, catchAndReturn, retry 연산자가 있습니다.

catch

메서드설명비고
catch(_ handler:)이 연산자는 옵저버블Error 항목을 방출하게 된다면 옵저버블과 구독을 종료하고, 다른 옵저버블의 항목을 방출합니다.
첫 번째 매개변수로 대체할 옵저버블을 반환하는 클로저를 전달해야 합니다.
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum MyError: Error {
    case error
}

let subject = PublishSubject<Int>()
subject
    .catch { _ in Observable<Int>.of(-1, -2, -3) }
    .subscribe { print($0) }
    .disposed(by: disposeBag)

subject.onNext(10)
subject.onNext(20)
subject.onNext(30)

subject.onError(MyError.error)

catchAndReturn

메서드설명비고
interval(_ preiod:scheduler:)이 연산자는 옵저버블Error 항목을 방출하게 된다면 옵저버블과 구독을 종료하고, 기본 값을 대신 방출합니다.
첫 번째 매개변수로 옵저버블 타입과 동일한 기본 값을 전달해야 합니다.
-
1
2
3
4
5
6
7
8
9
10
11
let subject = PublishSubject<Int>()
subject
    .catchAndReturn(-1)
    .subscribe { print($0) }
    .disposed(by: disposeBag)

subject.onNext(10)
subject.onNext(20)
subject.onNext(30)

subject.onError(MyError.error)

retry

메서드설명비고
retry(_ maxAttempts:)이 연산자는 옵저버블Error 항목을 방출하게 된다면 옵저버블과 구독을 종료하고, 새롭게 다시 구독합니다(시퀀스를 재시작).
첫 번째 매개변수로 최대 얼마나 시퀀스를 재시작할지 값을 전달해야 합니다.
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var attempts = 1

let source = Observable<Int>.create { observer in
    let currentAttempts = attempts
    print("- #\(currentAttempts) START")
    
    if attempts < 3 {
        observer.onError(MyError.error)
        attempts += 1
    }
    
    observer.onNext(10)
    observer.onNext(20)
    observer.onCompleted()
    
    return Disposables.create {
        print("- #\(currentAttempts) END")
    }
}

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

retryWhen

메서드설명비고
retry(when:)이 연산자는 옵저버블Error 항목을 방출하게 된다면 옵저버블과 구독을 종료하고, 트리거 옵저버블이 항목을 방출할 때, 새롭게 다시 구독합니다(시퀀스를 재시작).
첫 번째 매개변수로 트리거 옵저버블을 전달해야 합니다.
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var attempts = 1
let trigger = PublishSubject<Int>()

let source = Observable<Int>.create { observer in
    let currentAttempts = attempts
    print("- #\(currentAttempts) START")
    
    if attempts < 3 {
        observer.onError(MyError.error)
        attempts += 1
    }
    
    observer.onNext(10)
    observer.onNext(20)
    observer.onCompleted()
    
    return Disposables.create {
        print("- #\(currentAttempts) END")
    }
}

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

참고 자료

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.