簡體   English   中英

Scala:異常模式匹配

[英]Scala: Exception Pattern Matching

我需要定義一個提供上下文信息的Exception ,並將此信息存儲在Map 為了避免錯誤的鍵名,我定義了以下Enumeration

object ContextValueName extends Enumeration {

  type ContextValueName = Value

  val Value1 = Value("Value1")
  val Value2 = Value("Value2")
  val ValueN = Value("ValueN")

  implicit def toString(name: ContextValueName) = name.toString
}

這是Exception代碼:

import ContextValueName._

trait MyException extends RuntimeException {

  val errorCode: Int
  val contextValues: Map[ContextValueName, Option[String]]
}

object MyException {

  def apply(
    message: String, _errorCode: Int, _contextValues: Map[ContextValueName, Option[String]]
  ): MyException = new RuntimeException(message) with MyException {
    val errorCode: Int = _errorCode
    val contextValues: Map[ContextValueName, Option[String]] = _contextValues.withDefault(_ => None)
  }

  def unapply(exception: MyException) = {
    if (exception eq null) None
    else Some((
      exception.errorCode,
      exception.contextValues
    ))
  }
}

最后,這是我如何處理MyException類型的MyException

callService("myService").map { result =>
  ...
}.recover {
  case e@MyException(1, contextValues) =>
    Logger.debug(s"error invoking myService: ${contextValues(Value1).get}")
  case NonFatal(e) =>
    Logger.error(s"unhandled error: ${e.getMessage}")
}

問題是,即使拋出的異常類似於MyException(1, Map(Value1 -> "too busy")) ,也永遠不會執行第一個case語句,並且執行始終落在最后一個case語句中。 我想念什么嗎?

也許您可以使用Try,這對於Scala來說應該更自然一些。

Try {
   callService("myService")
} match {
  case Success(s) => // something you do when you succeed
  case Failure(ex) => ex match {
    case ex@MyException(1, contextValues) =>
      Logger.debug(s"error invoking myService: ${contextValues(Value1).get}")
    case NonFatal(ex) =>
      Logger.error(s"unhandled error: ${ex.getMessage}")
  }
}

小安慰,但FWIW,IWFM。

object Test extends App {
    import util._
    val res = Try (throw MyException("help", 1, Map(Value1 -> Option("bad")))) recover {
      case e@MyException(1, vals) => vals
    }
    Console println res

    import concurrent._
    import duration.Duration._
    import ExecutionContext.Implicits._
    val f = Future (throw MyException("help", 1, Map(Value1 -> Option("bad")))) recover {
      case e@MyException(1, vals) => vals
    }
    Console println Await.result(f, Inf)
}

暫無
暫無

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

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