簡體   English   中英

如何不拋出異常?

[英]How to NOT throw an exception?

我有下面的Slick代碼,給定一個ID返回一個客戶(如果存在)。 如果出現問題(例如連接斷開),則Failure子句將引發異常:

   def read (id: Int): Future[Option[Customer]] = {
      val db = // .... 
      val customers = TableQuery[CustomerDB]
      val action = customers.filter(_.id === id).result
      val future = db.run(action.asTry)
      future.map{
        case Success(s) => 
          if (s.length>0)
            Some(s(0))
          else
            None
        case Failure(f) => throw new Exception (f.getMessage)
      }
   }

現在,我的理解是,在Scala中,應該使用Try,而不是使用try / catch / finally的異常。 此外,不應引發任何異常。 但是,如果未引發異常,如何通知上層發生問題?

Future本身已經具有內部Try。 因此,我要說的是,您只需要展平(我簡化了代碼,但也有點復雜):

  future.flatMap {
    case Success(s) => Future.successful(s.headOption)
    case Failure(f) => Future.failed(f)
  }

結果處於failed狀態時的Future會通知調用者執行失敗(帶有原始包裝異常)。 否則,成功。

報告錯誤的正確方法是使用Either。

trait Error
case class NotFound(id: Int) extends Error
case class QueryFailed(msg: String) extends Error

def read (id: Int): Future[Either[Error, Customer]] = {
   val db = // .... 
   val customers = TableQuery[CustomerDB]
   val action = customers.filter(_.id === id).result
   val future = db.run(action.asTry)
   future.map{
      case Success(s) => 
         if (s.length>0)
           Right(s(0))
         else
           Left(NotFound(id))

      case Failure(f) => Left(QueryFailed(f.getMessage))
   }
}

好的,總的來說,您可以使用Future.successful或Future.failed(msg:String)來“信號”獲得值的上層(又稱調用方法)。

更好的方法

但是,一種好的方法是在失敗的情況下在Future上使用.recoverWith{}

例如:

def getUserFromCloud (userId: String): Future[String] = Future{
  cloudProviderApi.getUsername(userId)
}.recoverWith{
  Future.failed(s"$userId does not exist.")    
}  

那調用方法呢?

好吧,您只需將成功與underscode映射,然后通過使用restore處理錯誤:

getUserFromCloud("test").map(_ => {
    //In case of success
}).recover{
    //In case of failure, like return BadRequest. 
}

有關recoverrecover更多的recoverWith ,如果您有興趣的話: Scala恢復或recoverWith

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM