简体   繁体   中英

Scala Play framework futures

I have 3 methods: a, b, and c. Method a has some logic and it calls method b. Method b makes an api call returning Future[String]. If the returned value from method b is a certain value, method c is called. Method c makes another api call returning another Future[String].

def a: String = Action { request =>
  val x = b("hello")
  x
}

def b(y: String): Future[String] = {
  val x = ws.url(url).post(y).map { response =>
    val value = response.body
    val z = if (response.body === "hi") response.body else c(response.body)
    z
  }
  x
}

def c(z: String): Future[String] = {
  val x = ws.url(url).post(z).map { response =>
    response.body
  }
  x
}

Something like the code above. Eventually I want to parse everything into a json object, but I'm having trouble getting the Futures as regular strings. I'm new to scala and would appreciate some input.

You'll want something like this:

  def a: Action[AnyContent] = Action.async { _ =>
    b("hello").map(s => Ok(s))
  }

  def b(y: String): Future[String] = {
    ws.url(url).post(y).flatMap { response =>
      if (response.body == "hi") Future.successful(response.body) else c(response.body)
    }
  }

  def c(z: String): Future[String] = {
    ws.url(url).post(z).map { response =>
      response.body
    }
  }

A few things.

1) The type of your method a will be an Action[AnyContent] , since you are creating a Play Action . It's common to see people omit the type of action methods and let the compiler figure it out. Note if your action is more sophisticated (eg it reads a JSON request body) then its type might be Action[something_else] (eg Action[JsValue] if you're using Play Json).

2) Because b returns a future, you need to create the Action using Action.async which takes a function of type Request => Future[Response] (before you were calling Action.apply which takes a function of type Request => Response ).

3) In A , you need to map the String in the Future to a Response ; I do this using Ok (ie HTTP 200), although of course you can use whatever's appropriate.

4) In b , flatMap is your friend, because c returns a Future[String] and thus you end up with a Future[Future[String]] when you use map ... flatMap flattens that to a Future[String] .

5) You need to wrap the first branch of your if statement in Future.successful , such that both branches return the same type, Future[String] . Future.successful just builds a Future that is already completed.

6) Finally, you don't need to declare values x , y and z ; each expression resolves to its value, which really tidies things up.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM