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

如何从数据拉取与数据库保存操作返回Result<Unit>

问题分析与解决方案

原代码问题

原代码的类型不匹配是因为onSuccess/onFailure是副作用函数,它们的返回值不会改变原Result的类型——你最后返回的还是remoteDataSource.fetch()返回的Result<Foo>,而函数要求返回Result<Unit>,自然会报错。

另外原代码逻辑存在漏洞:onSuccess里的localDataSource.save()结果没有被正确向上传递,哪怕保存失败,最终也可能返回错误的结果。

优化后代码的隐患

你尝试的fold方案无法捕获本地保存的失败:onSuccess仅执行了localDataSource.save(),但它的返回值被丢弃了,fold处理的依然是远程返回的Result<Foo>——哪怕本地保存失败,fold的onSuccess分支依然会执行,返回Result.success(Unit),完全不符合需求。

正确实现方式

方式一:嵌套处理Result(最直观)

通过fold处理远程Result,在远程成功时直接返回本地保存的Result,最终统一输出Result<Unit>:

suspend fun add(csv: String): Result<Unit> {
    return try {
        remoteDataSource.fetch(csv).fold(
            onSuccess = { foo ->
                // 远程拉取成功,直接返回本地保存的Result<Unit>
                localDataSource.save(foo)
            },
            onFailure = { e ->
                // 远程拉取失败,包装为Result<Unit>类型的失败结果
                Result.failure<Unit>(e)
            }
        )
    } catch (e: Exception) {
        e.printStackTrace()
        Result.failure(e)
    }
}

这个方案能完整覆盖所有异常场景:

  • 远程拉取失败:直接进入onFailure分支返回失败结果
  • 本地保存失败:直接返回localDataSource.save()的失败结果
  • 任何未被Result封装的异常:被外层try-catch捕获并处理

方式二:用runCatching简化链式调用

如果remoteDataSource.fetch()和localDataSource.save()本身可能抛出未被封装进Result的异常,可通过runCatching包裹整个流程:

suspend fun add(csv: String): Result<Unit> {
    return runCatching {
        val foo = remoteDataSource.fetch(csv).getOrThrow()
        localDataSource.save(foo).getOrThrow()
    }.onFailure { e ->
        e.printStackTrace()
    }.fold(
        onSuccess = { Result.success(Unit) },
        onFailure = { Result.failure(it) }
    )
}

逻辑说明:

  1. 远程拉取失败时,getOrThrow()抛出异常,进入全局onFailure
  2. 远程成功但本地保存失败时,同样触发getOrThrow()抛出异常
  3. 所有异常被runCatching捕获,最终统一转换为Result<Unit>类型

关键注意点

  • 不要依赖onSuccess/onFailure传递结果,它们仅用于执行日志这类副作用,不会改变原Result的类型或值
  • 确保Result的类型转换是显式的,要么通过fold分支返回对应类型,要么通过getOrThrow()配合runCatching统一处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 05:05:48