从 Scala 未来完成返回值
Returning value from Scala future completion
来自 Java 背景,一段时间以来我一直在尝试自学 Scala。作为其中的一部分,我正在做一个小型宠物项目,该项目公开了一个 HTTP 端点,该端点将车辆的 registration number
与 owner
和 return 的状态相对应。
为了提供更多上下文,我使用 Slick 作为异步执行数据库操作的 FRM,并且 return 是 Future
。
基于这个 Future 的输出,我想将 status
变量设置为 return 返回给客户端。
这里是代码
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) 始终打印空字符串,方法 returns 也是如此。有人可以解释为什么吗?
我什至尝试将 var status
标记为 @volatile var status
,它仍然计算为空字符串。
我知道,以上不是功能性的处理方式,因为我处于静音状态。为这种情况编写代码的简洁方法是什么。
- 我能找到的几乎所有示例都描述了如何映射
Success
的结果或通过执行 println
来处理 Failure
。我想做的不止于此。
- 有哪些好的小项目可以参考?特别是,遵循 TDD。
而不是依赖 status
在闭包内部完成,您可以 recover
在 Future[T]
上处理异常,如果它们发生,总是 returns你想要的结果。这是利用 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
方法仅用于测试目的。
来自 Java 背景,一段时间以来我一直在尝试自学 Scala。作为其中的一部分,我正在做一个小型宠物项目,该项目公开了一个 HTTP 端点,该端点将车辆的 registration number
与 owner
和 return 的状态相对应。
为了提供更多上下文,我使用 Slick 作为异步执行数据库操作的 FRM,并且 return 是 Future
。
基于这个 Future 的输出,我想将 status
变量设置为 return 返回给客户端。
这里是代码
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) 始终打印空字符串,方法 returns 也是如此。有人可以解释为什么吗?
我什至尝试将
var status
标记为@volatile var status
,它仍然计算为空字符串。我知道,以上不是功能性的处理方式,因为我处于静音状态。为这种情况编写代码的简洁方法是什么。
- 我能找到的几乎所有示例都描述了如何映射
Success
的结果或通过执行println
来处理Failure
。我想做的不止于此。 - 有哪些好的小项目可以参考?特别是,遵循 TDD。
而不是依赖 status
在闭包内部完成,您可以 recover
在 Future[T]
上处理异常,如果它们发生,总是 returns你想要的结果。这是利用 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
方法仅用于测试目的。