디버깅 (Debugging)

doOnNext / doOnComplete / doOnError / doOnEach / doOnSubscribe / doOnDispose / doOnLifeCycle

디버깅 (Debugging)

doOn···()


try-catch 를 사용할 수 없어 중간 연산자 doOn···() 함수들을 이용하여 강제로 부수 효과를 일으켜 디버깅 해야한다.


doOnNext() / doOnComplete() / doOnError()


doOnNext() 는 데이터 발행(onNext()) 시 호출하는 함수이다.

doOnComplete() 는 모든 데이터의 발행(onComplete()) 이 완료되었을 때 호출하는 함수이다.

doOnError() 는 데이터 발행 시 중간에 에러(onError())가 발생하였을 때 호출하는 함수이다.

// 성공
fun main() = runBlocking {
    val observer: Observer<Int> = object: Observer<Int> {
        override fun onSubscribe(d: Disposable) {
            println("onSubscribe()")
        }

        override fun onNext(t: Int) {
            println("onNext() - $t")
        }

        override fun onError(e: Throwable) {
            println("onError() - ${e.message}")
        }

        override fun onComplete() {
            println("onComplete()")
        }
    }

    Observable.just(1, 2, 3)
        .doOnNext { println("doOnNext() - $it") }
        .doOnError { println("doOnError() - ${it.message}") }
        .doOnComplete { println("doOnComplete()") }
        .subscribe(observer)

    delay(1000)
}


// onSubscribe()
// doOnNext() - 1
// onNext() - 1
// doOnNext() - 2
// onNext() - 2
// doOnNext() - 3
// onNext() - 3
// doOnComplete()
// onComplete()
// 에러
fun main() = runBlocking {
    val observer: Observer<Int> = object : Observer<Int> {
        override fun onSubscribe(d: Disposable) {
            println("onSubscribe()")
        }

        override fun onNext(t: Int) {
            println("onNext() - $t")
        }

        override fun onError(e: Throwable) {
            println("onError() - ${e.message}")
        }

        override fun onComplete() {
            println("onComplete()")
        }
    }

    Observable.just(1, 2, 0)
        .map { 100 / it }
        .doOnNext { println("doOnNext() - $it") }
        .doOnError { println("doOnError() - ${it.message}") }
        .doOnComplete { println("doOnComplete()") }
        .subscribe(observer)

    delay(1000)
}


// onSubscribe()
// doOnNext() - 1
// onNext() - 1
// doOnNext() - 2
// onNext() - 2
// doOnError() - / by zero
// onError() - / by zero



doOnEach()


doOnNext(), doOnComplete(), doOnError() 를 한번에 처리하는 함수로, Notification 객체가 전달되고 isOnNext(), isOnComplete(), isOnError() 로 무슨 이벤트인지 구분할 수 있다.

fun main() = runBlocking<Unit> {
    Observable.just(1, 2, 3)
        .doOnEach {
            when {
                it.isOnNext -> {
                    println("doOnNext() - ${it.value}")
                }
                it.isOnError -> {
                    println("doOnError() - ${it.error?.message}")
                }
                it.isOnComplete -> {
                    println("doOnComplete()")
                }
                else -> {
                    println("Unknown")
                }
            }
        }
        .subscribe(println("$it")

    delay(1000)
}


// doOnNext() - 1
// 1
// doOnNext() - 2
// 2
// doOnNext() - 3
// 3
// doOnComplete()



doOnSubscribe() / doOnDispose()


doOnSubscribe()Observable 구독(subscribe()) 시 호출하는 함수이다.

doOnDispose()Observable 구독 해지(dispose()) 시 호출하는 함수이다.

fun main() = runBlocking {
    val observer = Observable.interval(100, TimeUnit.MILLISECONDS)
        .doOnSubscribe { println("doOnSubscribe()") }
        .doOnDispose { println("doOnDispose()") }
        .subscribe { println(it) }

    delay(300)
    observable.dispose()
    delay(300)
}


// doOnSubscribe()
// 0
// 1
// 2
// doOnDispose()



doOnLifeCycle()


doOnSubscribe(), doOnDispose() 함수를 한 번에 호출하는 함수이다.

fun main() = runBlocking {
    val observer = Observable.interval(100, TimeUnit.MILLISECONDS)
        .doOnLifeCycle(
            { println("doOnSubscribe()") }, // doOnSubscribe()
            { println("doOnDispose()") } // doOnDispose()
        )
        .subscribe { println(it) }

    delay(300)
    observable.dispose()
    delay(300)
}


// doOnSubscribe()
// 0
// 1
// 2
// doOnDispose()
essential