RxSwift
[RxSwift] Error Handling
thoonk:
2024. 3. 8. 13:57
반응형
RxSwift에서 에러 핸들링에 관한 내용을 기록합니다.
RxSwift에서의 에러 관리
Catch
error 를 새로운 Observable 또는 값으로 처리
catch(_ handler:)
- 클로저를 매개변수로 받아 완전히 다른 형태의 observable로 변환
public func `catch`(_ handler: @escaping (Swift.Error) throws -> PrimitiveSequence<Trait, Element>)
-> PrimitiveSequence<Trait, Element> {
PrimitiveSequence(raw: self.source.catch { try handler($0).asObservable() })
}
- 예시
func getUser(id: Int) -> Observable<User> {
return network.getUser(id)
.catchError { error in
if let apiError = error as? APIError {
switch apiError.code {
case 404:
return Observable.empty()
case 401:
return Observable.error(AuthenticationError())
default:
return Observable.error(error)
}
} else {
return Observable.error(error)
}
}
}
catchAndReturn(_ element:)
- 에러를 무시하고 이전에 선언해둔 값을 반환함.
- catch 에 비해 제한적, 주어진 타입의 에러에 대한 값을 반환할 수 없음. → 모든 에러에 대한 동일한 값이 반환됨.
public func catchAndReturn(_ element: Element)
-> PrimitiveSequence<Trait, Element> {
PrimitiveSequence(raw: self.primitiveSequence.source.catchAndReturn(element))
}
Retry
에러 상황에서 제한적 또는 무제한으로 재시도하기
retry 연산자가 observable 에러에서 사용되면 observable 내 전체 작업을 반복한다는 것을 의미
retry(_ maxAttemptCunt:)
- 재시도를 설정하지 않으면 무제한, 횟수로 설정할 수 있음.
public func retry(_ maxAttemptCount: Int)
-> PrimitiveSequence<Trait, Element> {
PrimitiveSequence(raw: self.source.retry(maxAttemptCount))
}
- 예시
func getUser(id: Int) -> Observable<User> {
return network.getUser(id)
.retry(3)
.catchError { error in
if let apiError = error as? APIError {
switch apiError.code {
case 404:
return Observable.empty()
case 401:
return Observable.error(AuthenticationError())
default:
return Observable.error(error)
}
} else {
return Observable.error(error)
}
}
}
retry(when notificationHandler:)
- notificationHandler 는 TriggerObservable 타입이므로 Observable 또는 Subject 모두 될 수 있음.
- 또한, 임의적으로 retry 를 trigger 하는데 사용됨.
public func retry<TriggerObservable: ObservableType>(when notificationHandler: @escaping (Observable<Swift.Error>) -> TriggerObservable)
-> PrimitiveSequence<Trait, Element> {
PrimitiveSequence(raw: self.source.retry(when: notificationHandler))
}
- 네트워크 연결 상태에 따른 데이터 요청 재시도
let networkReachabilityObservable = Observable<Bool>.create { observer in
// 네트워크 연결 상태 변화 관찰
if isNetworkReachable {
observer.onNext(true)
} else {
observer.onNext(false)
}
}
let observable = Observable<Data> { observer in
// 네트워크 요청 수행
if !isNetworkReachable {
observer.onError(NetworkError())
} else {
// ...
}
}
observable
.retry(when: networkReachabilityObservable.filter { $0 }) // 네트워크 연결 활성화 시 재시도
.subscribe(
onNext: { data in
// 데이터 처리
},
onError: { error in
// 네트워크 연결 오류 처리
}
)
Materialize/dematerialize
- Observable 을 Observable<Event>로 변환
- 실패한 시퀀스를 디버깅할 수 있음.
- 외부 시퀀스를 종료하지 않으면서 에러를 처리할 때 유용함.
public func materialize() -> Observable<Event<Element>> {
Materialize(source: self.asObservable())
}
- 예시
trigger
.flatMapLatest {
return dataSource.fetchItems()
.materialize()
}
.subscribe(with: self, onNext: { owner, event in
switch event {
case .next(let items):
print(items)
case .error(let error):
// error 처리
case .completed:
break
}
})
.disposed(by: disposeBag)
- 커스텀 이벤트 로그
observableToLog.materialize()
.do(onNext: { (event) in
myAdvancedLogEvent(event)
})
.dematerialize()
부족한 점 피드백해주시면 감사합니다 :)
Ref.
반응형