안녕하세요! 후르륵짭짭 입니다.
머 한 것도 없는데, 벌써 한달이 지났습니다 ㅎㅎㅎ
요즘엔 React 개발에 나름 흥미를 가져가지고, 웹 개발도 작성 해볼까 생각 중입니다 ㅎㅎㅎ
사내에서 RxSwift를 사용할 때가 많은데,
특히 Error 처리에 대해서 다뤄볼까 합니다.
찾으면 많이 나오지만,,,, 전 헷갈렸던거 위주로만 ㅋㅋㅋ
** RxError Create **
1. Create 방식
let _ = Observable<Int>.create { emiter in
print("current cnt : \(self.cnt)")
if self.cnt % 2 == 0 {
emiter.onError(NSError(domain: "에러발생", code: 0))
}
emiter.onNext(self.cnt)
self.cnt += 1
return Disposables.create()
}
.subscribe(onNext:{ cnt in
print("result : \(cnt)")
})
2. 단순 함수형 방식
func errorHandler() -> Observable<Int> {
if cnt % 2 == 0 {
return .error(NSError(domain: "에러발생", code: 0))
}
return .just(cnt)
}
3. 함수내에 Create 방식
func errorHandler3() -> Observable<Int>{
return Observable<Int>.create { emiter in
if self.cnt != 10 {
print("Error 발생 - 1 cnt : \(self.cnt)")
emiter.onError(NSError(domain: "에러발생", code: 0))
}
emiter.onNext(self.cnt)
self.cnt += 1
return Disposables.create()
}
위와 같이 Create 방식을 참고하여 만들도록 하겠습니다.
** retry로 함수 호출 **
Error Handle 중에 retry가 있는데,
이 친구는 성공할 때 까지 무한 호출 입니다.
1.
let _ = Observable<Int>.create { emiter in
if self.cnt != 10 {
print("Error 발생 - 1 cnt : \(self.cnt)")
emiter.onError(NSError(domain: "에러발생", code: 0))
}
emiter.onNext(self.cnt)
self.cnt += 1
return Disposables.create()
}
.retry()
.subscribe(onNext:{ cnt in
print("result : \(cnt)")
})
//result
Error 발생 - 1 cnt : 0
Error 발생 - 1 cnt : 1
Error 발생 - 1 cnt : 2
Error 발생 - 1 cnt : 3
Error 발생 - 1 cnt : 4
Error 발생 - 1 cnt : 5
Error 발생 - 1 cnt : 6
Error 발생 - 1 cnt : 7
Error 발생 - 1 cnt : 8
Error 발생 - 1 cnt : 9
result : 10
2. 번과 같은 방식은 한번만 호출 되고 끝납니다.
let _ = errorHandler2()
.retry()
.subscribe(onNext:{ cnt in
print("result : \(cnt)")
})
//결과
Error 발생 - 2 cnt : 1
3.
let _ = errorHandler3()
.retry()
.subscribe(onNext:{ cnt in
print("result : \(cnt)")
})
//결과
Error 발생 - 1 cnt : 0
Error 발생 - 1 cnt : 1
Error 발생 - 1 cnt : 2
Error 발생 - 1 cnt : 3
Error 발생 - 1 cnt : 4
Error 발생 - 1 cnt : 5
Error 발생 - 1 cnt : 6
Error 발생 - 1 cnt : 7
Error 발생 - 1 cnt : 8
Error 발생 - 1 cnt : 9
result : 10
일를 통해서 Custom Error 를 다루기 위해서는 Create 방식이 필요합니다.
만약에 아래와 같이 겹치는 경우는 어떻게 될까요?
1. 선 Create 후 함수형 (Create 에러 발생)
let _ = errorHandler3()
.flatMap({_ in return self.errorHandler2()})
.retry()
.subscribe(onNext:{ cnt in
print("result : \(cnt)")
})
//결과
Error 발생 - 3 cnt : 0
Error 발생 - 3 cnt : 1
Error 발생 - 3 cnt : 2
Error 발생 - 3 cnt : 3
Error 발생 - 3 cnt : 4
Error 발생 - 3 cnt : 5
Error 발생 - 3 cnt : 6
Error 발생 - 3 cnt : 7
Error 발생 - 3 cnt : 8
Error 발생 - 3 cnt : 9
result : 10
2. 후 Create 선 함수형 (함수 에러 발생)
let _ = errorHandler2()
.flatMap({_ in return self.errorHandler3()})
.retry()
.subscribe(onNext:{ cnt in
print("result : \(cnt)")
})
//결과
Error 발생 - 2 cnt : 0
3. 선 Create 후 함수형 (함수 에러 발생)
func errorHandler3() -> Observable<Int>{
return Observable<Int>.create { emiter in
emiter.onNext(self.cnt)
self.cnt += 1
return Disposables.create()
}
}
func errorHandler2() -> Observable<Int> {
if cnt != 10 {
print("Error 발생 - 2 cnt : \(self.cnt)")
return .error(NSError(domain: "에러발생", code: 0))
}
return .just(cnt)
}
let _ = errorHandler3()
.flatMap({_ in return self.errorHandler2()})
.retry()
.subscribe(onNext:{ cnt in
print("result : \(cnt)")
})
//결과
Error 발생 - 2 cnt : 0
Error 발생 - 2 cnt : 1
Error 발생 - 2 cnt : 2
Error 발생 - 2 cnt : 3
Error 발생 - 2 cnt : 4
Error 발생 - 2 cnt : 5
Error 발생 - 2 cnt : 6
Error 발생 - 2 cnt : 7
Error 발생 - 2 cnt : 8
Error 발생 - 2 cnt : 9
result : 10
4. 후 Create 선 함수형 (Create 에러 발생)
func errorHandler2() -> Observable<Int> {
return .just(cnt)
}
func errorHandler3() -> Observable<Int>{
return Observable<Int>.create { emiter in
if self.cnt != 10 {
print("Error 발생 - 3 cnt : \(self.cnt)")
emiter.onError(NSError(domain: "에러발생", code: 0))
}
emiter.onNext(self.cnt)
self.cnt += 1
return Disposables.create()
}
}
let _ = errorHandler2()
.flatMap({_ in return self.errorHandler3()})
.retry()
.subscribe(onNext:{ cnt in
print("result : \(cnt)")
})
위의 실험 결과를 보면 단독으로 함수형만 있을 경우에는
에러가 발생 했을 때, 한번만 호출되는 반면
Create가 있다면 어디서 에러가 발생했는지는 중요하지 않고
무조건 호출이 되는 것 같다!
** retry의 호출 위치 **
만약에 retry가 구역마다 있을 때는??
1.
{1 - 함수형 }retry {2 - Create형} retry 구역으로 나눠지게 된다.
따라서 {1}에서 문제가 없이 retry를 지나갔으면
{2}에서 문제가 발생하더라도 {1}로 넘어가지 않는다.
func errorHandler2() -> Observable<Int> {
print("errorHander2 호출 : \(cnt)")
return .just(cnt)
}
func errorHandler3() -> Observable<Int>{
return Observable<Int>.create { emiter in
if self.cnt != 10 {
print("Error 발생 - 3 cnt : \(self.cnt)")
emiter.onError(NSError(domain: "에러발생", code: 0))
}
emiter.onNext(self.cnt)
self.cnt += 1
return Disposables.create()
}
}
let _ = errorHandler2()
.retry()
.flatMap({_ in return self.errorHandler3()})
.retry()
.subscribe(onNext:{ cnt in
print("result : \(cnt)")
})
//결과
errorHander2 호출 : 0
Error 발생 - 3 cnt : 0
Error 발생 - 3 cnt : 1
Error 발생 - 3 cnt : 2
Error 발생 - 3 cnt : 3
Error 발생 - 3 cnt : 4
Error 발생 - 3 cnt : 5
Error 발생 - 3 cnt : 6
Error 발생 - 3 cnt : 7
Error 발생 - 3 cnt : 8
Error 발생 - 3 cnt : 9
result : 10
2.
{1 - Create} retry {2 - Create} retry 구조일 경우에는
2번에서 에러가 발생하더라도
아래와 같이 매번 {1 - Create}에서 Observable이 호출되니 주의해야한다.
func errorHandler3() -> Observable<Int>{
return Observable<Int>.create { emiter in
if self.cnt >= 5 && self.cnt < 10 {
print("Error 발생 - 3 cnt : \(self.cnt)")
emiter.onError(NSError(domain: "에러발생", code: 0))
}
emiter.onNext(self.cnt)
return Disposables.create()
}
}
let _ = Observable<Int>.create({emiter in
self.cnt += 1
print("Create 호출 : \(self.cnt)")
if self.cnt <= 5 {
print("Error 발생 - Create cnt :\(self.cnt)")
emiter.onError(NSError(domain: "에러발생", code: 0))
}
emiter.onNext(self.cnt)
return Disposables.create()
})
.retry()
.flatMap({_ in return self.errorHandler3()})
.retry()
.subscribe(onNext:{ cnt in
print("result : \(cnt)")
})
//결과
Create 호출 : 1
Error 발생 - Create cnt :1
Create 호출 : 2
Error 발생 - Create cnt :2
Create 호출 : 3
Error 발생 - Create cnt :3
Create 호출 : 4
Error 발생 - Create cnt :4
Create 호출 : 5
Error 발생 - Create cnt :5
Create 호출 : 6
Error 발생 - 3 cnt : 6
Create 호출 : 7
Error 발생 - 3 cnt : 7
Create 호출 : 8
Error 발생 - 3 cnt : 8
Create 호출 : 9
Error 발생 - 3 cnt : 9
Create 호출 : 10
result : 10
** Retry외 Error 처리 Rx 메소드 **
retry() 외에도
retry(max :)도 있고
retryWhen()도 있다.
그런데 이러한 내용은 검색하면 많이 나와서
https://rhammer.tistory.com/351
https://velog.io/@hansangjin96/RxSwift-Error-Handling-Operators
이 두개의 블로그만 참고해도 큰 도움이 될 것 같다!
'Xcode > Swift - PlayGround' 카테고리의 다른 글
PlayGround) Subscript란? (0) | 2022.03.15 |
---|---|
PlayGround) Serial에서 Async는 머지? (0) | 2022.02.28 |
PlayGround) Operation Queue - 2 (0) | 2022.01.17 |
PlayGround) Opeation Queue - 1 (0) | 2022.01.17 |
PlayGround) URLSessionDownload를 이용해서 PDF 파일 다운로드 (0) | 2021.12.26 |
댓글