scalahttpscala-dispatch

How should I wait for a scala dispatch (0.11.0) http get request to be completed?


I'm using the scala dispatch (0.11.0) library to send an HTTP GET request to a remote server. I want to wait for the response before executing the code which follows the request.

My request is of the form :

val req = :/("myurl.com") <:< myheaders OK as.Response(identity)

If I write :

val future = http(req)
future()
var res: String = null
future onComplete {
    case Success(r) => res = r.getResponseBody
    case _ => println("KO")
}
println(res)

I get null. This is also the case if I write :

val future = http(req)
var res: String = null
while (!future.isCompleted) {
    Thread.sleep(1000)
}
future onComplete {
    case Success(r) => res = r.getResponseBody
    case _ => println("KO")
}
println(res)

But with the following code :

val future = http(req)
var res: String = null
future onComplete {
    case Success(r) => res = r.getResponseBody
    case _ => println("KO")
}
while (!future.isCompleted) {
    Thread.sleep(1000)
}
println(res)

I get the expected response.

Does someone understand this ? It seems to me that calling Thread.sleep is not a good thing, could someone give me a hint on how I should handle this problem correctly ?

EDIT: @Randal Schulz thank you for your help, but as you posted in comments, I can't validate your answer.

As my problem was to wait (and do nothing else) until I get a valid response to an HTTP GET request, I think a satisfying way to do it is using Await.result. I removed the side-effect from my code. I used the option method to deal with Future failures (as I was interested only in successes), and I dealt with time out exception the classic way.

I think I could do it as wheaties mentionned, staying in Future, but I need more practice...


Solution

  • I finally managed to write what I wanted using futures :

    def loop(): Future[String] = {
        val future = http(req).option
        future flatMap ((x: Option[Response]) => x match {
            case Some(rep) => rep.getResponseBody
            case None => loop()
        }
    }
    

    Now I can use the result of this function without explicitely waiting for the response to come.