Handling errors in RxJS, RxSwift or RxJava
Scenario 1:
Scenario 2:
Scenario 3:
Catch the error, log it, and ignore it to suspend the operator chain’s execution without turning off the stream.
Rx provides operators that allow designing different strategies to apply the mentioned scenarios. Below are examples of the recommended strategies. It is emphasized that scenario number 1 should be avoided.
How to do it with RxJS?
And what about RxSwift?
network.getToken("api-key")
.concatMap { token in self.cache.storeTokenWithError(token) }
.concatMap { saved in self.network.getUser(username) }
.subscribe(onNext: { user in print("next:", user) },
onError: { error in print("error:", error) },
onCompleted: { print("completed") } )
.disposed(by: disposeBag)
network.getToken("api-key")
.concatMap { token in self.cache.storeTokenWithError(token) }
.concatMap { saved in self.network.getUser(username) }
.catchError({ error in Observable.just(User()) })
.subscribe(onNext: { user in print("next:", user) },
onError: { error in print("error:", error) },
onCompleted: { print("completed") } )
.disposed(by: disposeBag)
network.getToken("api-key")
.concatMap { token in self.cache.storeTokenWithError(token) }
.concatMap { saved in self.network.getUser(username) }
.catchError({ error in Observable.empty()
.do(onCompleted: { print(error) }) })
.subscribe(onNext: { user in print("next:", user) },
onError: { error in print("error:", error) },
onCompleted: { print("completed") } )
.disposed(by: disposeBag)
network.getToken("api-key")
.concatMap { token in self.cache.storeTokenWithError(token) }
.concatMap { saved in self.network.getUser(username) }
.retry(2)
.catchError({ error in Observable.empty()
.do(onCompleted: { print(error) }) })
.subscribe(onNext: { user in print("next:", user) },
onError: { error in print("error:", error) },
onCompleted: { print("completed") } )
.disposed(by: disposeBag)
network.getToken("api-key")
.concatMap { token in self.cache.storeTokenWithError(token) }
.concatMap { saved in self.network.getUser(username) }
.retryWhen{ errors in errors
.do(onNext: { ignored in print("retrying...") })
.delay(.seconds(2), scheduler: MainScheduler.instance)
.take(4)
.concat(Observable.error(SampleError()))}
.catchError({ error in Observable.empty()
.do(onCompleted: { print(error) }) })
.subscribe(onNext: { user in print("next:", user) },
onError: { error in print("error:", error) },
onCompleted: { print("completed") } )
.disposed(by: disposeBag)
And what about RxJava?
Example code for scenario 1 with RxJava:
network.getToken("api-key")
.concatMap(token -> cache.storeTokenWithError(token))
.concatMap(saved -> network.getUser(username))
.subscribe(element -> Log.d(TAG, "" + element),
throwable -> Log.e(TAG, "error:" + throwable),
() -> Log.d(TAG, "completed"))
Example code for scenario 2 with RxJava:
network.getToken("api-key")
.concatMap(token -> cache.storeTokenWithError(token))
.concatMap(saved -> network.getUser(username))
.onErrorResumeNext(throwable -> Observable.just(new User()))
.subscribe(user -> Log.d(TAG, "next: " + user),
throwable -> Log.e(TAG, "error: " + throwable),
() -> Log.d(TAG, "completed"))
Example code for scenario 3 with RxJava:
network.getToken("api-key")
.concatMap(token -> cache.storeTokenWithError(token))
.concatMap(saved -> network.getUser(username))
.onErrorResumeNext(throwable -> {
Log.d(TAG, Objects.requireNonNull(throwable.getMessage()));
return Observable.empty();
})
.subscribe(user -> Log.d(TAG, "next: " + user),
throwable -> Log.e(TAG, "error: " + throwable),
() -> Log.d(TAG, "completed"))
Example code for scenario 4 with RxJava:
network.getToken("api-key")
.concatMap(token -> cache.storeTokenWithError(token))
.concatMap(saved -> network.getUser(username))
.retry(2)
.onErrorResumeNext(throwable -> {
Log.d(TAG, Objects.requireNonNull(throwable.getMessage()));
return Observable.empty();
})
.subscribe(user -> Log.d(TAG, "next: " + user),
throwable -> Log.e(TAG, "error: " + throwable),
() -> Log.d(TAG, "completed"))
Example code for scenario 5 with RxJava:
network.getToken("api-key")
.concatMap(token -> cache.storeTokenWithError(token))
.concatMap(saved -> network.getUser(username))
.retryWhen(errors -> errors
.doOnNext(ignored -> Log.d(TAG, "retrying..."))
.delay(2, TimeUnit.SECONDS)
.take(4)
.concatWith(Observable.error(new Throwable())))
.onErrorResumeNext(throwable -> {
Log.d(TAG, Objects.requireNonNull(throwable.getMessage()));
return Observable.empty();
})
.subscribe(user -> Log.d(TAG, "next: " + user),
throwable -> Log.e(TAG, "error: " + throwable),
() -> Log.d(TAG, "completed"))
If you want to find more information about RxJS, RxSwift or RxJava, I recommend you check the guide book:
ConversionConversion EmoticonEmoticon