使用 Scala 中的模式匹配优化错误处理



我有一个如下所示的代码块来处理一些异常,我使用 if-else 语句,但我不喜欢它们相互嵌套,想知道是否可以使用模式匹配来使其更好?

try {
if (response.code < 200 || response.code > 299) {
throw new SearchClientFailure(s"API request failed with code ${response.code}, body ${response.body}")
} else {
if (isExceeded(response.body)) {
throw new SearchClientFailure("Exceed limit")
} else {
response.body
}
}
} catch {
case e: SearchClientFailure =>
if (queries.isEmpty) {
throw new SearchClientFailure
} else {
logger.warn(s"Failed to update the queries: ${e.message}")
queries
}
case _ =>
throw new SearchClientFailure
}

你可以做:

response match {
case r if (r.code < 200 || r.code > 299) => ...
case r if (isExceeded(r.body)) => ...
case r => r.body
}

更好吗?老实说,我不是 100% 确定,我真的不喜欢这种风格而不是你的风格。

顺便说一句,根据您使用的内容,您通常可以访问 response.isSuccess(( 或 response.code.isSuccess(( 而不是测试代码值

与其承担那些短投和接球的开销,我更想使用Either[String,Response]

Right(response).flatMap{r =>
if (r.code > 199 && r.code < 300) Right(r)
else Left(s"API request failed with code ${r.code}, body ${r.body}")
}.flatMap{r =>
if (isExceeded(r.body)) Left("Exceed limit")
else Right(r)
}.fold(msg => {
if (queries.isEmpty) throw new SearchClientFailure
logger.warn(s"Failed to update the queries: $msg")
queries
}, _.body)

唯一需要throw是抛出此上下文的那个。其他所有内容都在代码流中处理。

这是一个使用Either的版本

val apiResult: Either[String, String] =
if (response.code < 200 || response.code > 299)
Left(s"API request failed with code ${response.code}, body ${response.body}")
else if (isExceeded(response.body))
Left("Exceed limit")
else
Right(response.body)
apiResult match {
case Right(result) =>
result
case Left(message) if queries.nonEmpty =>
logger.warn(s"Failed to update the queries: $message")
queries
case _ =>
throw new SearchClientFailure
}

apiResult值存储错误字符串或 API 调用的正确结果。然后,如果需要,后续匹配可以检索原始错误字符串。

这遵循的约定是Right是正常/成功的结果,Left是错误情况或异常结果。

最新更新