Steve
Steve

Reputation: 23

How not to lose the asynchronous call?

How not to lose the asynchronous call anotherService.doSomething(res) ? Otherwise I'm not sure the piece of code will execute.

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

My idea is to store the result of the if and doing something like this:

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)

Upvotes: 0

Views: 70

Answers (2)

temonehm
temonehm

Reputation: 126

You can use scalaz and for-comprehension to make sure what is that did not work there.

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

I have not compiled it yet but I think it will working...

Upvotes: 1

Alvaro Carrasco
Alvaro Carrasco

Reputation: 6172

Using a for-comprehension is more idiomatic, you just need to provide a value for each 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)

Something like that.

Upvotes: 0

Related Questions