Search code examples
scalaakkalift

Scala return result from a Promise


Looking to achieve this:

HTTP request to REST API -> parse -> make async call to another API -> respond to http req with the result of the async call.

Currently, the code looks like:

 def getItems(param: String): LiftResponse = {

    @volatile var resp: LiftResponse = new BadResponse

    param.toLowerCase match {
      case "something" =>
        val req = Async call returning a Future
        req onSuccess {
          case items =>
            resp = new JsonResponse(items map (decompose(_)), S.getResponseHeaders(Nil), S.responseCookies, 200)
        }
        req onFailure {
          case fail => resp = new BadResponse
        }
        resp

      case _ => new OkResponse
    }
  }

But it looks like poor implementation.

What is the idiomatic Scala way to write the above?


Solution

  • I think you can try to inline @volatile var resp by:

    def getItems(param: String): LiftResponse = {
    
        param.toLowerCase match {
            case "something" =>
                val req = Async call returning a Future
                req.onComplete {
                    case Success(items) => new JsonResponse(items map (decompose(_)), S.getResponseHeaders(Nil), S.responseCookies, 200)
                    case Failure(t) => new BadResponse
                }
            case _ => new OkResponse
        }
    
    }
    

    --edit--

    sorry, onComplete returns Unit, how about using Await to get the result of future:

    import scala.concurrent.ExecutionContext.Implicits.global
    import scala.concurrent._
    import scala.concurrent.duration._
    
    def getItems(param: String): LiftResponse = {
    
        param.toLowerCase match {
            case "something" =>
                val req = Async call returning a Future
                val response = req map { items => 
                    new JsonResponse 
                } recover { 
                    case t:Throwable => new BadResponse
                }
                Await.result(response, Duration(100, MILLISECONDS))
            case _ => new OkResponse
        }
    
    }