如何从流程范围以异步方式调用挂起乐趣?

问题描述 投票:0回答:1

所以我从来没有做过这样的事情,所以我不知道哪种方法更好。

现在,我有一个用例,它以流程返回。为了简单起见,我没有附上我的代码,但它与此非常相似。

class UseCase constructor(
    private val userRepository: UserRepository,
    private val carRepository: CarRepository
){
    operator fun invoke(): Flow<Result<UserWithCars>>{
        return flow {
            try {
                //UserRepository under the hood returns with a RxJava Single<List<User>> list
                // But I converted to suspend fun with await() fun
                val users = userRepository.getAllUsers().await()
                fetchUserCars(users)
            }catch (e: Exception){
                emit(Result.Error())
            }
        }
    }

    private suspend fun fetchUserCars(userList: List<User>){
        userList.forEach { user->
            user.cars = try {
                //REpository also returns with a Single<>
                carRepository.getCarsByUserId(user.id).await()
            }catch (e: Exception){
                emptyList<Car>()
            }
        }
    }
}

如果我没记错的话,foreach将会同步执行。我不确定,但我认为 foreach 可以以异步方式执行,但我不知道如何执行。

当时,我使用了 ansyc{} fun ,但我需要位于协程范围内。

以前,用户单是平面地图化的,汽车被提取到用户对象。

return users.flatMap { user->
                    fetchCars(user)
                }

在 fetchCars() 方法中,我基本上将每个 userId 映射到查询汽车的 Single<>,因此我得到一个 List,之后,我使用了 RxJava Zip fun,但在这种情况下,我不确定, Zip 是如何运行的,因此每个 Single 都会彼此执行,或者同时执行

那我可以再优化一下吗,还是现在就可以了?

android kotlin coroutine
1个回答
0
投票

您关于使用

async
的说法是正确的,但您可能忽略了这样一个事实:您需要创建一个新的协程作用域以允许启动多个子进程。另外,因为我们不返回汽车列表,而是直接将其添加给用户,所以我们可以使用
launch
代替
async

private suspend fun fetchUserCars(userList: List<User>){
    coroutineScope { 
        userList.forEach { user->
            launch {
                user.cars = try {
                    //REpository also returns with a Single<>
                    carRepository.getCarsByUserId(user.id).await()
                }catch (e: Exception){
                    emptyList<Car>()
                }
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.