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

如何在Scala中使用for推导式处理错误场景并实现失败回滚

实现方案

你当前使用的for推导仅能处理Future执行成功的场景,无法在Either返回Left时触发自定义回滚逻辑,因此我们手动拆分每一步的执行、错误判断、回滚流程,确保失败时先执行对应回滚操作,再返回原始触发失败的错误。

完整实现代码

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Success, Failure}

val u1 = User("u1")
val w1 = Work("w1")

// 核心业务逻辑
val resp: Future[Either[MyError, User]] = UserApi.insert(u1).flatMap {
  // UserApi.insert失败,无前置操作,直接返回对应错误
  case Left(err) => Future.successful(Left(err))
  case Right(user) =>
    WorkApi.insert(w1).flatMap {
      // WorkApi.insert失败,先执行UserApi.delete回滚,再返回对应错误
      case Left(err) =>
        UserApi.delete(user).map(_ => Left(err))
      case Right(work) =>
        WorkApi.assign(w1).flatMap {
          // WorkApi.assign失败,依次执行WorkApi.delete、UserApi.delete回滚,再返回对应错误
          case Left(err) =>
            for {
              _ <- WorkApi.delete(work)
              _ <- UserApi.delete(user)
            } yield Left(err)
          // 所有操作执行成功,返回UserApi.insert的结果
          case Right(_) => Future.successful(Right(user))
        }
    }
}

println("ending...")

resp onComplete {
  case Success(r) => println(r)
  case Failure(t) => println(t)
}

case class User(name: String)
case class Work(name: String)

case class MyError(name: String)

object UserApi {
  def insert(user: User): Future[Either[MyError, User]] =
    if (user.name == "u1") Future(Right(user))
    else Future(Left(MyError("UserApi.insert")))
  def delete(user: User): Future[Either[MyError, String]] =
    Future(Right("UserApi.delete"))
}

object WorkApi {
  def insert(work: Work): Future[Either[MyError, Work]] =
    if (work.name == "w1") Future(Right(work))
    else Future(Left(MyError("WorkApi.insert")))

  def delete(work: Work): Future[Either[MyError, Work]] = Future(Right(work))

  def assign(work: Work): Future[Either[MyError, Work]] =
    if (work.name == "w1") Future(Right(work))
    else Future(Left(MyError("WorkApi.assign")))
}

逻辑说明

  • 完全基于Scala 2.13原生API实现,无第三方依赖
  • 错误返回始终为触发失败的对应API的原始错误,不会被回滚操作的结果覆盖
  • 回滚操作严格按需求顺序执行,不会遗漏前置操作的回滚
  • 所有流程执行成功时返回User类型的插入结果,符合需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 07:15:03