Thursday 31 January 2019

How to break RxJava chain on error Result?

I've inherited this codebase which uses RxJava2 and kotlin with a rather peculiar Result pattern for API calls. i.e. all API calls return Singles with a Result object (which is a sealed class of Success and Error types as shown below) i.e.

sealed class Result<T, E> {
    data class Success<T, E>(
            val data: T
    ): Result<T, E>()

    data class Error<T, E>(
            val error: E
    ): Result<T, E>()
}

Now I'm trying to chain together a bunch of API calls of these but need to terminate the chain on the first Result.Error in it and continue if not.

The only way I can think of is to zip all of the Singles and then have a zipper function that checks the type of each parameter and returns a Result.Error() with the first error it encounters. i.e. something like,

Singles.zip(
    repo1.makeCall1(arg),
    repo1.makeCall2(arg2),
    repo2.makeCall1(arg3)
) { result1, result2, result3 ->
    val data1 = when (result1) {
        is Result.Error -> return@zip Result.Error(result1.error)
        is Result.Success -> result1.data
    }
    val data2 = when (result2) {
        is Result.Error -> return@zip Result.Error(result2.error)
        is Result.Success -> result2.data
    }
    val data3 = when (result3) {
        is Result.Error -> return@zip Result.Error(result3.error)
        is Result.Success -> result3.data
    }

    return@zip Result.Success(MergedData(data1, data2, data3))
}

which works but looks really weird (and feels like a code smell with this huge ass zipper method). Also does not allow me to chain anything more after the last method (that checks if the Result is a Success / Error).

I feel it would be a lot more readable to be able to chain these calls and terminate on the first error but I don't know enough Rx to do this. Is there an operator or an approach that could help make this better?



from How to break RxJava chain on error Result?

No comments:

Post a Comment