์ƒˆ์†Œ์‹

๐Ÿ“ฑ iOS/-- RXSwift

(RxSwift) Error ๋‹ค๋ฃจ๊ธฐ, Retry, Catch

  • -

Observable -> Subscriber ๋กœ ErrorEvent๊ฐ€ ์ „๋‹ฌ๋˜๋ฉด, ๊ตฌ๋…์ด ์ข…๋ฃŒ๋˜๊ณ  ๋” ์ด์ƒ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌ๋ฐ›์ง€ ๋ชปํ•˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ ‡๊ฒŒ๋˜๋ฉด ๋” ์ด์ƒ ์ƒˆ๋กœ์šด ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด์„œ ํ•ธ๋“ค๋งํ•  ์ˆ˜ ์—†๊ฒŒ๋œ๋‹ค.
์ผ๋ฐ˜์ ์ธ์ƒํ™ฉ์—์„œ Observable์€ Network๋ฅผ ์š”์ฒญํ•˜๊ณ , Subscriber๋Š” UI๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค. ์ด๋•Œ ErrorEvent๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๊ตฌ๋…์ด ์ข…๋ฃŒ๋˜์–ด ๋” ์ด์ƒ UI๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ๋œ๋‹ค.
์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ catch ํ˜น์€ retry๋ฅผ ํ†ตํ•ด์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

Catch (Operator)

CatchError๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Next, Completed ์ด๋ฒคํŠธ๋Š” ํ‰์†Œ๋Œ€๋กœ ๊ตฌ๋…์ž์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค. ํ•˜์ง€๋งŒ ErrorEvent๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ƒˆ๋กœ์šด Observable์„ ์ƒ์„ฑํ•˜์—ฌ ๊ตฌ๋…์ž์—๊ฒŒ ์ „๋‹ฌํ•ด์ฃผ๊ฑฐ๋‚˜, ๊ธฐ๋ณธ๊ฐ’์„ ์ „๋‹ฌํ•˜์—ฌ UI ์—…๋ฐ์ดํŠธ๊ฐ€ ๋Š์–ด์ง€์ง€ ์•Š๋„๋ก ํ•  ์ˆ˜ ์žˆ๋Š” ์—ฐ์‚ฐ์ž์ด๋‹ค.

enum TError: Error{
    case testError
}
let bag = DisposeBag()
let subject = PublishSubject<Int>()
let recovery = PublishSubject<Int>()

subject
    .catch({ error in
        recovery // ์—๋Ÿฌ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„๋•Œ, ์ƒˆ๋กœ์šด ์˜ต์ €๋ฒ„๋ธ”์„ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค. (์›๋ž˜ ์˜ต์ €๋ฒ„๋ธ”๊ณผ ์ƒˆ๋กœ์šด ์˜ต์ €๋ฒ„๋ธ”์ด ๊ต์ฒด๋œ๋‹ค.)
    })
    .subscribe { print($0) }
    .disposed(by: bag)

subject.onNext(1)
subject.onError(TError.testError) // ์ด์‹œ์ ์—์„œ ๊ตฌ๋…์ด ์ข…๋ฃŒ๋œ๋‹ค.

subject.onNext(2) // ๊ตฌ๋…์ด ์ข…๋ฃŒ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜์‘ ์—†์Œ
recovery.onNext(188) // catch๋กœ ๋ฐ›์€ ์ƒˆ๋กœ์šด observable

catchAndReturn

let bag = DisposeBag()

enum MyError: Error {
    case error
}

let subject = PublishSubject<Int>()

subject
    .catchAndReturn(-199)
    .subscribe { print($0) }
    .disposed(by: bag)

subject.onNext(100)
subject.onError(MyError.error) // ์ง€์ •ํ•ด๋‘” ๊ธฐ๋ณธ๊ฐ’์ด return ๋˜๊ณ  completed ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœํ•œ๋‹ค.
subject.onNext(100) // ๋” ์ด์ƒ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐฉ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค.

Retry

CatchError์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Next, Completed ์ด๋ฒคํŠธ์—์„œ๋Š” ๋‹ฌ๋ผ์ง€๋Š”๊ฒŒ ์—†์ง€๋งŒ, ErrorEvent๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด Subscriber์—๊ฒŒ ์ „๋‹ฌํ•˜์ง€ ์•Š๊ณ  ๋‹ค์‹œ ์‹คํŒจํ–ˆ๋˜์ž‘์—…์„(์ฃผ๋กœ network ์ž‘์—…) ์‹œ๋„ํ•˜๊ฒŒ๋œ๋‹ค. ์ด๋•Œ ์žฌ์‹œ๋„ ํšŸ์ˆ˜๋„ ์ œํ•œ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

let bag = DisposeBag()

enum MyError: Error {
    case error
}

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 // 3์ด ๋„˜์–ด๊ฐˆ๋•Œ๊นŒ์ง€ ์žฌ์‹œ๋„๋ฅผ ํ•˜๋ฉด ์•„๋ž˜์˜ onNext์ด๋ฒคํŠธ๊ฐ€ ์ „๋‹ฌ๋˜๊ฒŒ๋œ๋‹ค.
    }

    observer.onNext(1)
    observer.onNext(2)
    observer.onCompleted()

    return Disposables.create {
        print("#\(currentAttempts) END")
    }
}

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

retry(When:)

๊ธฐ๋ณธ์ ์œผ๋กœ ErrorEvnet๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด retry๋ฅผ ์‹œ๋„ํ•œ๋‹ค๋Š”๊ฑด ๊ฐ™์ง€๋งŒ, retry๋ฅผ ๋ฐ”๋กœํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ์–ธ์ œํ• ์ง€ ์‹œ์ ์„์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.


let bag = DisposeBag()

enum MyError: Error {
    case error
}

var attempts = 1

let source = Observable<Int>.create { observer in
    let currentAttempts = attempts
    print("START #\(currentAttempts)")

    if attempts < 3 {
        observer.onError(MyError.error)
        attempts += 1
    }

    observer.onNext(1)
    observer.onNext(2)
    observer.onCompleted()

    return Disposables.create {
        print("END #\(currentAttempts)")
    }
}

let trigger = PublishSubject<Void>()

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



trigger.on(.next(())) // ์ด ์‹œ์ ์—์„œ retry๋ฅผ ์‹œ๋„ํ•˜๊ฒŒ๋œ๋‹ค.

'๐Ÿ“ฑ iOS > -- RXSwift' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

RxSwift (2) - Subject & Relay  (0) 2023.05.17
RxSwift (1) ์ฃผ์š” ๊ฐœ๋… (Observable , Subscribe, Disposable, Operator)  (0) 2023.05.17
Contents

ํฌ์ŠคํŒ… ์ฃผ์†Œ๋ฅผ ๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค

์ด ๊ธ€์ด ๋„์›€์ด ๋˜์—ˆ๋‹ค๋ฉด ๊ณต๊ฐ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.