You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在suspend函数中等待Flow执行完成后返回组装好的对象

解决方案

核心问题说明

你当前的代码无法返回的核心原因取决于transactionRepository.getAll返回的Flow类型:

  • 如果是有限流(发射固定数量值后主动结束):collect 会挂起直到Flow执行完毕,你只需要在collect代码块后直接返回account即可。
  • 如果是无限流(最常见的场景,比如Room返回的数据库可观察流,会持续监听数据变化永远不会主动结束):collect 会永久挂起,后续代码永远不会执行,这种情况需要调整实现方案。

场景1:只需获取一次当前最新数据(最常用)

使用first()终端操作符,拿到Flow发射的第一个值后立即终止收集,不会持续挂起:

override suspend fun getAccount(accountId: Int): Account {
    val account = Account(accountRepository.get(accountId))
    // 只取第一个发射的事务列表
    val transactions = transactionRepository.getAll(accountId)
        .mapIterable {
            val transaction = Transaction(it)
            val category = Category(categoryRepository.get(it.categoryId))
            transaction.category = category
            transaction.account = account
            return@mapIterable transaction
        }.first()
    
    account.transactions = transactions
    return account
}

场景2:Flow为有限流,需要等待所有发射完成

直接在collect后返回即可,collect会自动挂起直到Flow执行完毕:

override suspend fun getAccount(accountId: Int): Account {
    val account = Account(accountRepository.get(accountId))
    transactionRepository.getAll(accountId).mapIterable {
        val transaction = Transaction(it)
        val category = Category(categoryRepository.get(it.categoryId))
        transaction.category = category
        transaction.account = account
        return@mapIterable transaction
    }.collect {
        account.transactions = it
     }
    // Flow执行完成后会走到这里
    return account
}

场景3:需要持续监听数据变化返回最新的Account

这种场景不应该用suspend函数返回单个对象,直接将返回值改为Flow,每次数据变化自动发射新的组装后的Account:

override fun getAccount(accountId: Int): Flow<Account> {
    return flow {
        val baseAccount = Account(accountRepository.get(accountId))
        transactionRepository.getAll(accountId)
            .mapIterable {
                val transaction = Transaction(it)
                val category = Category(categoryRepository.get(it.categoryId))
                transaction.category = category
                transaction.account = baseAccount
                return@mapIterable transaction
            }.collect { transactions ->
                baseAccount.transactions = transactions
                emit(baseAccount)
            }
    }
}

内容的提问来源于stack exchange,提问作者DennisVA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 01:06:01