如何不丢失异步调用?

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")
}

我还没有编译它,但我认为它会工作...