58 lines
1.6 KiB
Plaintext
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]
|