如何不丢失异步调用?
How not to lose the asynchronous call?
如何不丢失异步调用anotherService.doSomething(res)
?否则我不确定这段代码是否会执行。
myDAO.update(param).map { // update() returns Future[Option[Object]]
case Some(row) =>
if (row.active) {
myDAO.selectUser(size).map { //selectUser() returns Future[Option[User]]
case Some(res) =>
anotherService.doSomething(res) //doSomething() returns Future[StandaloneWSResponse] but this line might not run without being able to keep track. This is my problem
case _ => Left(Wrong)
}
}
Right(...)
case None => Left(Wrong)
}
}
我的想法是存储 if 的结果并执行如下操作:
val v = if (row.active) {
myDAO.selectUser(size).map { //selectUser() returns Future[Option[User]]
case Some(res) =>
anotherService.doSomething(res) //doSomething() returns Future[StandaloneWSResponse]
case _ => Left(Wrong)
}
Future.successful(v)
使用 for-comprehension 更加地道,您只需要为每个 None:
提供一个值
for {
rowOpt <- myDAO.selectUser(size)
userOpt <- rowOpt.filter(_.active).fold(Future.successful(Option.empty[...])) {row =>
myDAO.selectUser(size)
}
resultOpt <- userOpt.fold(Future.succesful(Option.empty[...])) {user =>
anotherService.doSomething(res)
}
} yield resultOpt.toEither(Wrong)
类似的东西。
您可以使用 scalaz 和 for-comprehension 来确定在那里不起作用的是什么。
import scalaz._
val result = for {
updateObjResultOpt <- myDAO.update(param).toRightDisjunction("error when Update")
if(updateObjReesurtOpt.filter(_.active).nonEmpty)
userOptional <- myDAO.selectUser(size).toRightDisjunction("error when select user")
if(userOptional.nonEmpty)
otherResult <- anotherService.doSomething(res).toRightDisjunction("error when execute doSomething")
} yield otherResult
// if you want return Future[ValidationNel[String, StandaloneWSResponse]]
val validationNelResult = result.fold(error => Failure(NonEmptyList(error)), otherResult => Success(otherResult))
// if you want to return the Future[result], you can use pattern matching
val futureResult = validationNelResult.match {
case Success(data) => Ok("success")
case Failure(error) => BadRequest(error)
case _ => BadRequest("other error")
}
我还没有编译它,但我认为它会工作...
如何不丢失异步调用anotherService.doSomething(res)
?否则我不确定这段代码是否会执行。
myDAO.update(param).map { // update() returns Future[Option[Object]]
case Some(row) =>
if (row.active) {
myDAO.selectUser(size).map { //selectUser() returns Future[Option[User]]
case Some(res) =>
anotherService.doSomething(res) //doSomething() returns Future[StandaloneWSResponse] but this line might not run without being able to keep track. This is my problem
case _ => Left(Wrong)
}
}
Right(...)
case None => Left(Wrong)
}
}
我的想法是存储 if 的结果并执行如下操作:
val v = if (row.active) {
myDAO.selectUser(size).map { //selectUser() returns Future[Option[User]]
case Some(res) =>
anotherService.doSomething(res) //doSomething() returns Future[StandaloneWSResponse]
case _ => Left(Wrong)
}
Future.successful(v)
使用 for-comprehension 更加地道,您只需要为每个 None:
提供一个值for {
rowOpt <- myDAO.selectUser(size)
userOpt <- rowOpt.filter(_.active).fold(Future.successful(Option.empty[...])) {row =>
myDAO.selectUser(size)
}
resultOpt <- userOpt.fold(Future.succesful(Option.empty[...])) {user =>
anotherService.doSomething(res)
}
} yield resultOpt.toEither(Wrong)
类似的东西。
您可以使用 scalaz 和 for-comprehension 来确定在那里不起作用的是什么。
import scalaz._
val result = for {
updateObjResultOpt <- myDAO.update(param).toRightDisjunction("error when Update")
if(updateObjReesurtOpt.filter(_.active).nonEmpty)
userOptional <- myDAO.selectUser(size).toRightDisjunction("error when select user")
if(userOptional.nonEmpty)
otherResult <- anotherService.doSomething(res).toRightDisjunction("error when execute doSomething")
} yield otherResult
// if you want return Future[ValidationNel[String, StandaloneWSResponse]]
val validationNelResult = result.fold(error => Failure(NonEmptyList(error)), otherResult => Success(otherResult))
// if you want to return the Future[result], you can use pattern matching
val futureResult = validationNelResult.match {
case Success(data) => Ok("success")
case Failure(error) => BadRequest(error)
case _ => BadRequest("other error")
}
我还没有编译它,但我认为它会工作...