본문으로 바로가기
반응형

Observer 나 Subscriber 객체에 onError() 함수를 override하면 생산자에서 발생하는 error를 전달받을수 있습니다.

하지만 onError()을 사용하지 않고, 중간 연산자로 error을 처리하는 방법에 대해서 알아봅니다.


먼저 기본적으로 에러를 발생시키도록 코드를 작성합니다.

fun main(args: Array<String>) {
    Observable.range(1, 10)
        .map {
            if (it == 5) {
                throw Exception("Error!!!")
            } else {
                it
            }
        }
        .subscribeBy (
            onNext = { println(it) },
            onError = { e -> println(e) }
        )
}


예상대로 5를 찍으면 exception을 throw 합니다.

1

2

3

4

java.lang.Exception: Error!!!


onErrorReturnItem | onErrorReturn

에러가 발생시 특정값으로 교체하여 전달합니다.

물론 발생시 Observable의 생산은 중단됩니다.

fun main(args: Array) {
    Observable.range(1, 10)
        .map {
            if (it == 5) {
                throw Exception("Error!!!")
            } else {
                it
            }
        }
        .onErrorReturnItem(-1)
//        .onErrorReturn { e: Throwable -> -1 }
        .subscribeBy(onNext = { println(it) },
            onError = { e -> println(e) })
}


결과는 아래와 같습니다.

1

2

3

4

-1


Error 발생시 아이템을 -1로 반환하도록 onErrorReturnItem을 사용했습니다.

따라서 이를 수신받는 함수는 onNext() 입니다 . (onError()이 아닙니다.)

또한 주석을 풀고 onErrorReturn{...} 를 사용하여 Function<T,R>을 람다식으로 넣어줘도 됩니다.


onErrorResumeNext

Error 발생시 다른 Observable을 구독하도록 onErrorResumeNext를 사용할 수도 있습니다.
fun main(args: Array) {
    Observable.range(1, 10)
        .map {
            if (it == 5) {
                throw Exception("Error!!!")
            } else {
                it
            }
        }
        .onErrorResumeNext(Observable.just(3, 2, 1))
        .subscribeBy(onNext = { println(it) },
            onError = { e -> println(e) })
}

결과

1

2

3

4

3

2

1


retry

error 발생시 재시도 합니다.
보통 네트워크 요청후 응답을 받아올 경우 실패시 "X번 재시도 한다"라는 구현상황을 요청받습니다.
(저만 그런가요..;;;)
여기서는 명확하게 계속 에러를 발생 시키지만 "네트워크 실패시 세번 재시도 한다" 같은 시나리오를 구현 할 때 사용하기 적합한 연산자 입니다.

fun main(args: Array<String>) {
    val ob = Observable.range(1, 10)
        .map {
            if (it == 5) {
                throw Exception("Error!!!")
            } else {
                it
            }
        }

    ob.retry(2)
        .subscribeBy(onNext = { println(it) },
            onError = { e -> println(e) })

    println("---- retry with condition ----")
    ob.retry { retryCnt, e ->
        println("retry cnt:$retryCnt")
        if (retryCnt > 2) false else true
    }
        .subscribeBy(onNext = { println(it) },
            onError = { e -> println(e) })
}

단순히 retry(반복횟수)로 반복을 정의할 수 도 있으며, retry { retryCount, Throwable -> Boolean} 인 람다식으로 재시도 여부를 판단할 수 있습니다.

1

2

3

4

1

2

3

4

1

2

3

4

java.lang.Exception: Error!!!

---- retry with condition ----

1

2

3

4

retry cnt:1

1

2

3

4

retry cnt:2

1

2

3

4

retry cnt:3

java.lang.Exception: Error!!!


retryUntil

retryUntilretry{..} 와 유사합니다.
fun main(args: Array<String>) {
    val ob = Observable.range(1, 10)
        .map {
            if (it == 5) {
                throw Exception("Error!!!")
            } else {
                it
            }
        }

    var retryCnt = 0
    ob.retryUntil {
        if (retryCnt == 3) {
            true
        } else {
           println("Retry!!!")
            retryCnt++
            false
        }
    }
        .subscribeBy(onNext = { println(it) },
            onError = { e -> println(e) })
}

결과

1

2

3

4

Retry!!!

1

2

3

4

Retry!!!

1

2

3

4

java.lang.Exception: Error!!!


반응형