I want to get Result<T> class(or something l...
# coroutines
u
I want to get Result<T> class(or something like it) after finished launch block. Because I used invokeOnCompletion with CoroutineExceptionHandler. But It is not enough for me. There is no value of success case. So I made this code. But I want to find a better way. If somebody knows a better way. comment please.
Copy code
launchCatching(
    block = {
        getRandomNumber()
    },
    result = {
        println("result is $it")
    }
).invokeOnCompletion {
    it is Throwable
}

fun <T> CoroutineScope.launchCatching(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T,
    result: (result: Result<T>) -> Unit
) = launch(context, start) {
    result(
        runCatching {
            block()
        }
    )
}

fun <T> CoroutineScope.launchCatching(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T,
    onSuccess: (value: T) -> Unit,
    onFailure: (exception: Throwable) -> Unit
) = launch(context, start) {
    runCatching {
        block()
    }.fold(
        onSuccess,
        onFailure
    )
}
d
Instead of
launch
why not just have a suspend function. This seems a bit round about.
u
First I can english not well. Maybe I didn’t understand your meaning well. Please understand.
I want to know suspend function is successful or not with value or failure reason in same block after finish. A suspend function run by
launch
is just finished meet a exception. If I want to know what exception is. I can know using by
invokeOnCompletion
. (If I adding CoroutineExceptionHandler) But It is separated successful and failure block. successful is run on coroutine and failure is others. So I tried encapsulate suspend function by Result class. But I don’t want modify compile option because of this document (https://github.com/Kotlin/KEEP/blob/success-or-failure/proposals/stdlib/success-or-failure.md) And Next I’m wrapped
runCatching
or
try / catch
each suspend function. But It is simplicity repetition. So I tried it.
e
If you create a suspending function and add a try/catch inside, when you catch the error you can simply return the “failure” version of your custom
Result<T>
. As an example:
Copy code
sealed class Result<T>
class SuccessResult<T>(val result: T): Result<T>
class FailureResult<T>(val error: Throwable): Result<T>

suspend fun doesNotThrowAnyErrors(): Result<String> {
  return try {
    SuccessResult(mayThrowSomeError())
  } catch (e: Exception) {
    FailureResult(e)
  }
}

// Usage
suspend fun usageExample() {
  when (val computationResult = doesNotThrowAnyErrors()) {
    is SuccessResult -> println(computationResult.value)
    is FailureResult -> println("Got an error!")
  }
}
If you want a result of something asynchronously dispatched, you might want to use
async {}
rather than
launch {}
as the former actually returns a computation result. Only use
launch {}
if you don’t care about the result of the launched coroutine.
u
Thank you for yours comments. Maybe I had wrong idea to solve my problem. I’ll try other ways and your suggestion.
👍 1