Is it possible to return a value from a canceled coroutine?

I’d like to be able to define functions which perform some asynchronous actions and return some MyResult. I’d like to be able to cancel the coroutines for these functions while still having them return MyResult. Inside the functions, I can have try {...} catch(CancellationException) return MyResult(..), but how could I actually get that result returned from the catch block? Even though the CancellationException is caught and not rethrown, any variation of awaiting on the job for the function’s coroutine seems to just also get a JobCancellationException. Is this actually possible in Kotlin? - to have a coroutine which can be canceled but essentially suppress the cancellation and return a result?

Ohh, it’s an interesting question. I don’t feel very comfortable with this, but I think you should not use builtin cancellations, but your own, custom cancellation signalling.

Cancellations in coroutines were designed to support the structured concurrency model, to allow cancellations to propagate through the job hierarchy. We can’t return from the cancelled coroutines, because in most cases if the coroutine has been cancelled, that means the consumer of its result also has been cancelled. Or it explicitly said: “I’m not interested in your result anymore”.

As said above, I would probably go with my own, custom cancellation signalling. But maybe there is a better way.

Thanks for the response @broot! That makes sense and seems completely reasonable. I ended up going with a helper utility which provides a function a scope to run its operations in. That way, that scope can be cancelled independently of the scope for the function itself, allowing the function to handle the cancellation as an early termination and control its response to the calling function.

eg.

suspend fun myFun() = helper { scope ->
    try {
        withContext(scope.coroutineContext) {
            ...
        }
    } catch(e: CancellationException) {
        ...
    }
}