58 lines
1.6 KiB
Plaintext

== Why is this an issue?
There are two ways to define asynchronous functions in Kotlin:
* using the modifier `suspend` in the function declaration
* creating an extension function on `CoroutineScope`
The `suspend` modifier is generally used for functions that might take some time to complete. The caller coroutine might potentially be suspended.
Functions that start a coroutine in the background and return before said coroutine has completed running should be extension functions on `CoroutineScope`. This helps to clarify the intention of such a function. Further, such functions should not be suspending, as suspending functions should only return once all the work they are designed to perform is complete.
Functions returning `Flow` or `Channel` should return the result immediately and may start a new coroutine in the background. As a consequence, such functions should not be suspending and if they launch a coroutine in the background, they should be declared as extension functions on `CoroutineScope`.
=== Noncompliant code example
[source,kotlin]
----
suspend fun f(): Flow<Int> {
val flow = flow {
emit(1)
}
delay(500L)
return flow
}
----
[source,kotlin]
----
suspend fun f(): Channel<Int> {
val ch = Channel<Int>()
ch.send(1)
return ch
}
----
=== Compliant solution
[source,kotlin]
----
fun f(): Flow<Int> = flow {
emit(1)
}
----
[source,kotlin]
----
fun CoroutineScope.f(): Channel<Int> {
val ch = Channel<Int>()
launch {
ch.send(1)
}
return ch
}
----
== Resources
* https://elizarov.medium.com/coroutine-context-and-scope-c8b255d59055[Coroutine Context and Scope]