来自Java背景,我一直在尝试自学Scala一段时间。作为其中的一部分,我正在做一个小型宠物项目,该项目公开了一个HTTP端点,该端点根据owner
保存车辆的registration number
并返回状态。
为了提供更多的上下文,我使用Slick作为FRM,它异步执行DB操作并返回Future
。根据这个Future的输出,我想将status
变量设置为返回到客户端。
这里,是代码
def addVehicleOwner(vehicle: Vehicle): String = {
var status = ""
val addFuture = db.run((vehicles returning vehicles.map(_.id)) += vehicle)
addFuture onComplete {
case Success(id) => {
BotLogger.info(LOGTAG, s"Vehicle registered at $id ")
status = String.format("Registration number - '%s' mapped to owner '%s' successfully", vehicle.registration,
vehicle.owner)
println(s"status inside success $status") //--------- (1)
}
case Failure(e: SQLException) if e.getMessage.contains("SQLITE_CONSTRAINT") => {
status = updateVehicleOwner(vehicle)
BotLogger.info(LOGTAG, s"Updated owner='${vehicle.owner}' for '${vehicle.registration}'")
}
case Failure(e) => {
BotLogger.error(LOGTAG, e)
status = "Sorry, unable to add now!"
}
}
exec(addFuture)
println(s"Status=$status") //--------- (2)
status
}
// Helper method for running a query in this example file:
def exec[T](sqlFuture: Future[T]):T = Await.result(sqlFuture, 1 seconds)
这在Java中相当简单。使用Scala,我面临以下问题:
- 期望值在(1)处打印,但(2)总是打印空字符串,方法返回的也是这样。有人能解释一下原因吗?
我甚至尝试将
var status
标记为@volatile var status
,它仍然计算为空字符串。我知道,以上不是功能性的做事方式,因为我正在静音状态。对于这种情况,写代码的干净方式是什么?
- 几乎所有的例子,我可以找到描述如何映射
Success
的结果或处理Failure
通过做println
。我想做的不止这些。 - 我可以参考的小项目有哪些好的参考资料?特别是,遵循TDD。
不依赖status
在闭包内完成,您可以在Future[T]
之上使用recover
处理异常,并且总是返回您想要的结果。这是利用了Scala表达式的特性:
val addFuture =
db.run((vehicles returning vehicles.map(_.id)) += vehicle)
.recover {
case e: SQLException if e.getMessage.contains("SQLITE_CONSTRAINT") => {
val status = updateVehicleOwner(vehicle)
BotLogger.info(
LOGTAG,
s"Updated owner='${vehicle.owner}' for '${vehicle.registration}'"
)
status
}
case e => {
BotLogger.error(LOGTAG, e)
val status = "Sorry, unable to add now!"
status
}
}
val result: String = exec(addFuture)
println(s"Status = $result")
result
注意,Await.result
不应该在任何生产环境中使用,因为它会同步阻塞Future
,这与您实际想要的完全相反。如果您已经使用Future
来委派工作,您希望它以异步方式完成。我假设你的exec
方法只是为了测试的目的。