Scala Language
Manejo de errores
Buscar..
Tratar
Usando Try with map
, getOrElse
y flatMap
:
import scala.util.Try
val i = Try("123".toInt) // Success(123)
i.map(_ + 1).getOrElse(321) // 124
val j = Try("abc".toInt) // Failure(java.lang.NumberFormatException)
j.map(_ + 1).getOrElse(321) // 321
Try("123".toInt) flatMap { i =>
Try("234".toInt)
.map(_ + i)
} // Success(357)
Usando Try
con el patrón de coincidencia:
Try(parsePerson("John Doe")) match {
case Success(person) => println(person.surname)
case Failure(ex) => // Handle error ...
}
Ya sea
Diferentes tipos de datos para error / éxito
def getPersonFromWebService(url: String): Either[String, Person] = {
val response = webServiceClient.get(url)
response.webService.status match {
case 200 => {
val person = parsePerson(response)
if(!isValid(person)) Left("Validation failed")
else Right(person)
}
case _ => Left(s"Request failed with error code $response.status")
}
}
Coincidencia de patrones en cualquier valor
getPersonFromWebService("http://some-webservice.com/person") match {
case Left(errorMessage) => println(errorMessage)
case Right(person) => println(person.surname)
}
Convertir cualquier valor a opción
val maybePerson: Option[Person] = getPersonFromWebService("http://some-webservice.com/person").right.toOption
Opción
El uso de valores null
no se recomienda, a menos que se interactúe con el código Java heredado que se espera que sea null
. En su lugar, la Option
debería usarse cuando el resultado de una función puede ser algo ( Some
) o nada ( None
).
Un bloque try-catch es más apropiado para el manejo de errores, pero si la función no puede devolver nada legítimamente, la Option
es apropiada para el uso y es simple.
Una Option[T]
puede ser Some(value)
(contiene un valor de tipo T
) o None
:
def findPerson(name: String): Option[Person]
Si no se encuentra ninguna persona, None
puede ser devuelta. De lo contrario, se devuelve un objeto de tipo Some
contienen un objeto Person
. Lo que sigue son formas de manejar un objeto de tipo Option
.
La coincidencia de patrones
findPerson(personName) match {
case Some(person) => println(person.surname)
case None => println(s"No person found with name $personName")
}
Usando map y getOrElse
val name = findPerson(personName).map(_.firstName).getOrElse("Unknown")
println(name) // Prints either the name of the found person or "Unknown"
Utilizando pliegue
val name = findPerson(personName).fold("Unknown")(_.firstName)
// equivalent to the map getOrElse example above.
Convertir a Java
Si necesita convertir un tipo de Option
a un tipo de Java con capacidad nula para la interoperabilidad:
val s: Option[String] = Option("hello") s.orNull // "hello": String s.getOrElse(null) // "hello": String val n: Option[Int] = Option(42) n.orNull // compilation failure (Cannot prove that Null <:< Int.) n.getOrElse(null) // 42
Manejo de errores originados en futuros
Cuando se lanza una exception
desde un Future
, puede (debería) usar recover
para manejarlo.
Por ejemplo,
def runFuture: Future = Future { throw new FairlyStupidException }
val itWillBeAwesome: Future = runFuture
... lanzará una Exception
desde dentro del Future
. Pero viendo que podemos predecir una Exception
de tipo FairlyStupidException
con una alta probabilidad, podemos manejar este caso específicamente de una manera elegante:
val itWillBeAwesomeOrIllRecover = runFuture recover {
case stupid: FairlyStupidException =>
BadRequest("Another stupid exception!")
}
Como puede ver, el método dado para recover
es un PartialFunction
sobre el dominio de todos los Throwable
, por lo que puede manejar solo algunos tipos y luego dejar que el resto entre en el nivel de manejo de excepciones en los niveles más altos en la pila Future
.
Tenga en cuenta que esto es similar a ejecutar el siguiente código en un contexto no Future
:
def runNotFuture: Unit = throw new FairlyStupidException
try {
runNotFuture
} catch {
case e: FairlyStupidException => BadRequest("Another stupid exception!")
}
Es realmente importante manejar las excepciones generadas en Future
s porque la mayoría de las veces son más insidiosas. Por lo general, no se ponen en su lugar porque se ejecutan en un contexto de ejecución y un hilo diferente, y por lo tanto no le piden que los corrija cuando suceden, especialmente si no nota nada en los registros o en el comportamiento de solicitud.
Usando las cláusulas try-catch
Además de las construcciones funcionales, como Try
, Option
y Either
para el manejo de errores, Scala también admite una sintaxis similar a la de Java, utilizando una cláusula try-catch (con un bloque de potencial también). La cláusula catch es una coincidencia de patrón:
try {
// ... might throw exception
} catch {
case ioe: IOException => ... // more specific cases first
case e: Exception => ...
// uncaught types will be thrown
} finally {
// ...
}
Convertir excepciones en uno u otro tipo de opción
Para convertir excepciones en Either
o Option
tipos, puede utilizar métodos que proporcionan en scala.util.control.Exception
import scala.util.control.Exception._
val plain = "71a"
val optionInt: Option[Int] = catching(classOf[java.lang.NumberFormatException]) opt { plain.toInt }
val eitherInt = Either[Throwable, Int] = catching(classOf[java.lang.NumberFormatException]) either { plain.toInt }