how do I turn this code into coroutines? <https://...
# coroutines
o
how do I turn this code into coroutines? https://hastebin.com/ukuxatodew.kotlin I figured out that I am able to do this
Copy code
viewModelScope.launch(<http://dispatchers.io|dispatchers.io>) {
            val filterSources = try {
                listOf(
                    launch { getLocation.execute() },
                    launch { getCategory.execute() },
                    launch { getPeriod.execute() },
                    launch { getDateRange.execute() }
                ).joinAll().
            } catch (e: Throwable) {

            }

        }
but unable to figure out how to get that to a map where i can use the stuff inside
f
check the thread just above yours, you can use
async
and then
awaitAll
on the list
o
lol
thanks
I am not sure really how to map them into an actual result that I can then cast to what I want like in the original code snippet
if you awaitAll or joinAll or whateverAll, where is the final array or list of results?
f
awaitAll
returns a List with the result of your tasks. However, if your tasks return different types, then you'll just get a list of
Any
- in this case, don't make a list and launch the
async
individually and then wait for them
o
yes that’s what i’ve already concluded, correct it comes back Any
you sure got this stuff down huh
f
I've been around a while 😄
o
so this is what I’ve got in the end
Copy code
val tasks = listOf(
    async { getLocation.execute() },
    async { getCategory.execute() },
    async { getPeriod.execute() },
    async { getDateRange.execute() }
)


val location = (tasks[0].await() as Optional<GetLocation.Location>).orNull()
this location is a
GetLocation.Result.Success
and it has a member inside called
location
, THAT Member is what i want to cast, how do I get that member out of
tasks[0].await()
?
cause right now the cast is failing because Success cannot be Cast to Optional, that
location
inside the Success is the one that’s Optional, not the parent Success object
f
if your function return disparate types, then I wouldn't make a list
Copy code
val locationDeferred = async { getLocation.execute() },
val categoryDeferred = async { getCategory.execute() },
// others
val location = locationDeffered.await()
val category = categoryDeferred.await()
// await others
o
I didnt end up calling awaitAll on the list though
f
then even less of a reason to use a list
o
for sure, but i dont think spreading the calls into variables will change how this cast is ending up though
f
note that unless you
await
the deferred, you won't get any result from it - it runs as soon as you launch it, but any result of error is stored until you call await
o
yes I’m aware of that part
f
what's the return type for
getLocation.execute()
?
o
GetLocation.Result, which is a sealed class with Success(val location) and Error(val throwable)
I think i should cast it to success first 😛
I mean Result
yeap
f
if you don't use a list then no cast is necessary, I think you're making things a bit too cumbersome by putting them in a list
o
yea yea forget the list, im doing them seperately, but since the return type is a
Result
class (with Success and Error) I can’t simply cast that entire thing into the type of Success’ member variable in 1 go
it clear now
f
right, your
Result
class might have a
fold
or similar that you can use to get the value or error
o
yeap
what the hell is fold 😮
a thing for later
f
for example,
Copy code
sealed interface Result<out T> {
    class Success<T>(val value: T) : Result<T>
    class Failure(val error: Throwable) : Result<Nothing>
}

inline fun <R, T> Result<T>.fold(
    onSuccess: (value: T) -> R,
    onFailure: (exception: Throwable) -> R,
): R = when (this) {
    is Result.Success -> onSuccess(value)
    is Result.Failure -> onFailure(error)
}
and you would use it like so
Copy code
repoResponse.fold(
            onSuccess = { response ->
                // handle successful response
            },
            onFailure = { error ->
                // handle error
            }
        )
o
holy shit
that is nice
thank you
so I’ve done this, and it now looks like this
Copy code
viewModelScope.launch(<http://dispatchers.io|dispatchers.io>) {
            val locationDeferred = async { getLocation.execute() }
            val categoryDeferred = async { getCategory.execute() }
            val periodDeferred = async { getPeriod.execute() }
            val dateRangeDeferred = async { getDateRange.execute() }

            var location : GetLocation.Location? = null
            var dateRange : DateRange? = null
            lateinit var category : Category
            lateinit var period : Period

            locationDeferred.await().fold(
                onSuccess = { response ->
                    location = response.orNull()
                },
                onFailure = {
                    logger.log(it)
                }
            )

            categoryDeferred.await().fold(
                onSuccess = { response ->
                    category = response
                },
                onFailure = {
                    logger.log(it)
                }
            )
but when coming back to this code it doesnt trigger again
was Observable.combineLatest doing something that solved that ? im not sure