본문 바로가기
Rx

RxJava 디버깅과 예외처리 -1 ( 디버깅, doOnNext, doOnComplete, doOnError 함수)

by 봄석 2018. 12. 31.

본 내용은 필자가 학습한 내용을 정리하는 내용입니다.

대부분 의 내용이 아래 책의 내용이므로 원서를 구매해서 직접보시는걸 추천드립니다!

RxJava 프로그래밍 리액티브 프로그래밍 기초부터 RxAndroid까지 한 번에

유동환 , 박정준 지음 | 한빛미디어 | 2017년 09월 04일 출간

http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788968488658&orderClick=LAV&Kc=


저자님의 블로그

https://brunch.co.kr/@yudong#info




디버깅

보통 코딩하는 중에 로그를 넣는 이유는 잘못된부분을 찾고 잘못되었을 때 대처하기 위함입니다. 하지만 RxJava는 코드는 로그를 넣을수 있는 공간이 없습니다. Observable로 시작하는 업스트림(upstream)과 그것을 받아서 처리하는 다운스트림(downstream)이 동일한 문장으로 이루어져 있기 때문입니다. 즉 , 전체 동작을 선언적으로 만들수 있으므로 전체 맥락에 대한 가독성은 높아지지만 예외 코드를 어떻게 넣어야 하는지에 대해 어려움이 있습니다.


이번에는 앞에서 다뤄본적 있는 doOnComplete() 함수와 doOnNext() 함수를 포함한 doOnXXX() 계열의 함수를 알아보겠습니다. 

원래 함수형 프로그래밍은 부수효과를 없도록 하는것이 원칙이지만 doOnXXX()계열 함수는 오히려 부수효과를 일으켜서 내가 작성하는 코드가 문제없는지 알아볼 수 있게 합니다.



doOnNext() , doOnComplete(), doOnError() 함수

doOnNext() , doOnComplete(), doOnError() 라는 세 함수는 Observable의 알림 이벤트에 해당합니다. Observable이 어떤 데이터를 발행할 때는 onNext, 중간에 에러가 발생하면 onError, 모든 데이터를 발행하면 onComplete 이벤트가 발생합니다. 이 세가지 함수는 이벤트에 맞게 원하는 내용을 처리할 수 있습니다.


doOnNext() , doOnComplete(), doOnError() 함수 활용 예

String[] orgs={"1","3","5"};
Observable<String> source=Observable.fromArray(orgs);
        
source.doOnNext(data->Log.d("onNext() ",data))
    .doOnComplete(()->Log.d("onComplete()"))
    .doOnError(e->Log.e("onError()",e.getMessage()))
    .subscribe(Log::i);




실행결과 

main | onNext()  | debug = 1
main | value = 1
main | onNext()  | debug = 3
main | value = 3
main | onNext()  | debug = 5
main | value = 5

main | debug = onComplete()


모두  main 스레드에서 실행되었고 각 이벤트 발생시에는 debug 로그를 출력합니다. 

실제로 Observable이 구독자에게 발행한 데이터는 value로 표시했습니다.

다음은 에러를 확인해보겠습니다


onError() 이벤트 확인 예

Integer[] divider={10,5,0};
        
Observable.fromArray(divider)
    .map(div->1000/div)
    .doOnNext(data->Log.d("onNext() ",data))
    .doOnComplete(()->Log.d("onComplete()"))
    .doOnError(e->Log.e("onError :",e.getMessage()))

     .subscribe(Log::i);


Observable은 1000을 어떤 수로 나누며 , 나누는 수로 10, 5, 0 을 대입합니다. 어떤 숫자도 0으로 나눌수 없기 떄문에 에러가 발생합니다.


실행결과

main | onNext()  | debug = 100
main | value = 100
main | onNext()  | debug = 200
main | value = 200
main | onError : | error = / by zero
io.reactivex.exceptions.OnErrorNotImplementedException: / by zero
    at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:704)
    at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:701)
    at io.reactivex.internal.observers.LambdaObserver.onError(LambdaObserver.java:74)

    at io.reactivex.internal.operators.observable.ObservableDoOnEach$DoOnEachObserver.onError(ObservableDoOnEach.java:119)


doOnError() 함수로 onError 이벤트가 발생했을때의 에러메시지인 /by zero 를 출력한 후 아레는 표준 입출력의 자세헌 에러 메시지를 출력합니다.에러 이름은 OnErrorNotImplementedException입니다.




댓글