Scala Language
La gestion des erreurs
Recherche…
Essayer
Utilisation de Try avec map
, getOrElse
et 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)
En utilisant Try
avec la correspondance de motif:
Try(parsePerson("John Doe")) match {
case Success(person) => println(person.surname)
case Failure(ex) => // Handle error ...
}
Non plus
Différents types de données pour erreur / succès
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")
}
}
Correspondance de motif sur l'une ou l'autre valeur
getPersonFromWebService("http://some-webservice.com/person") match {
case Left(errorMessage) => println(errorMessage)
case Right(person) => println(person.surname)
}
Convertir l'une ou l'autre valeur en option
val maybePerson: Option[Person] = getPersonFromWebService("http://some-webservice.com/person").right.toOption
Option
L'utilisation de valeurs null
est fortement déconseillée, sauf si elle interagit avec du code Java hérité qui attend null
. Au lieu de cela, Option
doit être utilisée lorsque le résultat d'une fonction peut être quelque chose ( Some
) ou rien ( None
).
Un bloc try-catch est plus approprié pour la gestion des erreurs, mais si la fonction peut légalement renvoyer rien, Option
est appropriée à utiliser et simple.
Une Option[T]
peut être soit Some(value)
(contient une valeur de type T
), soit None
:
def findPerson(name: String): Option[Person]
Si personne n'est trouvé, None
ne peut être retourné. Sinon, un objet de type Some
contenant un objet Person
est renvoyé. Ce qui suit sont des manières de gérer un objet de type Option
.
Correspondance de motif
findPerson(personName) match {
case Some(person) => println(person.surname)
case None => println(s"No person found with name $personName")
}
Utiliser la carte et getOrElse
val name = findPerson(personName).map(_.firstName).getOrElse("Unknown")
println(name) // Prints either the name of the found person or "Unknown"
En utilisant fold
val name = findPerson(personName).fold("Unknown")(_.firstName)
// equivalent to the map getOrElse example above.
Conversion en Java
Si vous avez besoin de convertir un type d' Option
en un type Java nul pour l'interopérabilité:
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
Gestion des erreurs provenant des futures
Lorsqu'une exception
est lancée depuis un Future
, vous pouvez (devrait) utiliser recover
pour le gérer.
Par exemple,
def runFuture: Future = Future { throw new FairlyStupidException }
val itWillBeAwesome: Future = runFuture
... lancera une Exception
partir de l' Future
. Mais comme nous pouvons prédire qu’une Exception
de type FairlyStupidException
avec une probabilité élevée, nous pouvons traiter ce cas de manière élégante:
val itWillBeAwesomeOrIllRecover = runFuture recover {
case stupid: FairlyStupidException =>
BadRequest("Another stupid exception!")
}
Comme vous pouvez le voir, la méthode donnée pour recover
est une fonction PartialFunction
sur le domaine de Throwable
, vous pouvez donc gérer certains types seulement et laisser le reste aller dans la gestion des exceptions à des niveaux supérieurs de la pile Future
.
Notez que ceci est similaire à l'exécution du code suivant dans un contexte non Future
:
def runNotFuture: Unit = throw new FairlyStupidException
try {
runNotFuture
} catch {
case e: FairlyStupidException => BadRequest("Another stupid exception!")
}
Il est très important de gérer les exceptions générées dans Future
s car elles sont souvent insidieuses. Ils ne sont généralement pas présents dans votre visage, car ils s'exécutent dans un contexte d'exécution et un thread différents, et ne vous invitent donc pas à les corriger lorsqu'ils surviennent, surtout si vous ne remarquez rien dans les journaux ou le comportement du serveur. application.
Utilisation de clauses try-catch
En plus des constructions fonctionnelles telles que Try
, Option
et Either
pour la gestion des erreurs, Scala prend également en charge une syntaxe similaire à celle de Java, en utilisant une clause try-catch (avec également un bloc potential). La clause catch est une correspondance de modèle:
try {
// ... might throw exception
} catch {
case ioe: IOException => ... // more specific cases first
case e: Exception => ...
// uncaught types will be thrown
} finally {
// ...
}
Convertir des exceptions en deux types d'option
Pour convertir des exceptions en types Either
ou Option
, vous pouvez utiliser des méthodes fournies dans 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 }