目前我的錯誤處理沒有按照我的意愿作業,這就是我想要做的:
- UserApi.insert 失敗,回傳錯誤,不要繼續
- WorkApi.insert 失敗,呼叫 UserApi.delete 后回傳錯誤
- WorkApi.assign 失敗,呼叫 WorkApi.delete 和 UserApi.delete 后回傳錯誤
所以綜上所述,UserApi.insert 被呼叫,如果成功,繼續#2。如果 WorkApi.insert 成功,請繼續。依此類推,如果當前步驟失敗,則必須反轉上一步。
此外,為失敗的 Api 呼叫回傳最相關的錯誤也很重要。
如果所有呼叫都成功,我想回傳第一個呼叫值,即User
.
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 = for {
insertResp <- UserApi.insert(u1)
workInsertResp <- WorkApi.insert(w1)
workAssignResp <- WorkApi.assign(w1)
} yield insertResp
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.x,我沒有使用其他框架,只是普通的 Scala。
https://scastie.scala-lang.org/OV4Ax58qQ1S3R3fFUikSbw
uj5u.com熱心網友回復:
首先,我會建議不要混合Future
和Either
這樣。Future
有自己的表示失敗的方式,并且將 an 包裝Either
在 aFuture
意味著您需要處理失敗的Future
情況和 的Left
情況Either
,這可能會導致一些令人困惑的代碼。
問題提供的代碼中沒有異步執行,所以 usingFuture
是多余的,可以Either
直接使用型別。但是,我假設您想將這些方法替換為進行實際(異步)API 呼叫的方法,在這種情況下,您將希望使用Future
不帶Either
. Future
要求失敗值擴展Throwable
,因此這需要更改為MyError
:
case class MyError(name: String) extends Exception(name)
其次,將或Future.apply
用于非阻塞構造并不是一個好習慣。這并不明顯,但這實際上會導致在隱式執行背景關系中被調度為任務,而不是在當前執行緒上同步計算。當結果微不足道時,最好使用或創建完成。Future(Right(user))
Future(Left(MyError("UserApi.insert")))
Right(user)
Future.successful
Future.failed
Future
通過這些更改,新的方法實作是:
object UserApi {
def insert(user: User): Future[User] =
if (user.name == "u1") Future.successful(user)
else Future.failed(MyError("UserApi.insert"))
def delete(user: User): Future[String] =
Future.successful("UserApi.delete")
}
object WorkApi {
def insert(work: Work): Future[Work] =
if (work.name == "w1") Future.successful(work)
else Future.failed(MyError("WorkApi.insert"))
def delete(work: Work): Future[Work] =
Future.successful(work)
def assign(work: Work): Future[Work] =
if (work.name == "w1") Future.successful(work)
else Future.failed(MyError("WorkApi.assign"))
}
uj5u.com熱心網友回復:
我相信這就是你所描述的。
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
val resp: Future[Either[MyError,User]] =
UserApi.insert(u1).flatMap{_.fold(
{err => Future.successful(Left(err))}
,usr => WorkApi.insert(w1).flatMap{_.fold(
{err => UserApi.delete(u1); Future.successful(Left(err))}
, _ => WorkApi.assign(w1).map{_.fold(
{err => WorkApi.delete(w1); UserApi.delete(u1); Left(err)}
, _ => Right(usr)
)}
)}
)}
. . . //and the rest of your code
測驗:
import scala.concurrent.duration.DurationInt
concurrent.Await.result(resp, 9999.millis)
//res0: Either[MyError,User] = Right(User(u1))
如您所見,您當前的代碼設計不太適合您布置的任務。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/318738.html
標籤:斯卡拉
上一篇:如何發送多條訊息作為我的來源