Description
The "Extract function refactoring" section in the documentation (link on the website and in the repo) describes the process of extracting out a suspend function and makes a couple statements about idiomatic patterns that I believe are misleading.
The documentation describes a pretty general case when a user may want to call a coroutine builder from a suspend function:
But what if the extracted function contains a coroutine builder which is invoked on the current scope? In this case, the suspend modifier on the extracted function is not enough.
The documentations offers a few solutions (including making the suspend function in question an extension function on CoroutineScope
which I believe generally wouldn't be in line with conventions around extensions on CoroutineScope
) but notably includes the following:
The idiomatic solution is to have either an explicit
CoroutineScope
as a field in a class containing the target function or an implicit one when the outer class implementsCoroutineScope
.
This isn't really the case, right? For most use cases I imagine the coroutineScope
(or supervisorScope
) function is the best solution as it:
- Can be called from a suspend function
- Provides a
CoroutineScope
in which one can call coroutine builders, and - Respects structured concurrency since the scope that's created is a child of the scope in which the suspend function is called.
Additionally, the fact that coroutineScope
will wait for any launched children to complete and suspend as necessary feels in line with reasonable behavior to expect when calling a suspend function.
I believe that's preferable to needing to have an explicit CoroutineScope
as a field which is not practical in many use cases and the documentation should be updated as such — I'm happy to take a stab at it if contributions are welcome.