2013-03-28 15 views
5

Próbuję wysłać prośbę o dodanie do aplikacji Pusher, ale mam problem ze zwróceniem prawidłowy typ, niedopasowanie typu; znaleziono: scala.concurrent.Future [play.api.libs.ws.Response] wymagane: play.api.libs.ws.Responseniedopasowanie typu; found: scala.concurrent.Future [play.api.libs.ws.Response] wymagany: play.api.libs.ws.Response

def trigger(channel:String, event:String, message:String): ws.Response = { 
val domain = "api.pusherapp.com" 
val url = "/apps/"+appId+"/channels/"+channel+"/events"; 
val body = message 

val params = List( 
    ("auth_key", key), 
    ("auth_timestamp", (new Date().getTime()/1000) toInt), 
    ("auth_version", "1.0"), 
    ("name", event), 
    ("body_md5", md5(body)) 
).sortWith((a,b) => a._1 < b._1).map(o => o._1+"="+URLEncoder.encode(o._2.toString)).mkString("&"); 

    val signature = sha256(List("POST", url, params).mkString("\n"), secret.get); 
    val signatureEncoded = URLEncoder.encode(signature, "UTF-8"); 
    implicit val timeout = Timeout(5 seconds) 
    WS.url("http://"+domain+url+"?"+params+"&auth_signature="+signatureEncoded).post(body 
} 

Odpowiedz

4

Żądanie robisz z post jest asynchroniczny. To wywołanie natychmiast zwraca, ale nie zwraca obiektu Response. Zamiast tego zwraca obiekt Future[Response], który będzie zawierał obiekt Response po zakończeniu asynchronicznego żądania http.

Jeśli chcesz zablokować wykonanie aż wniosek zostanie zakończona, wykonaj następujące czynności:

val f = Ws.url(...).post(...) 
Await.result(f) 

Zobacz więcej na temat futures here.

+0

W 99% przypadków nie powinieneś czekać na Asynchronizację. Wszystkie niezbędne narzędzia do pracy z przyszłością są widoczne w ramach. –

+0

To nie jest rozwiązanie, którego szukasz ... –

+0

dziękuję Mariusowi i Julienowi, masz rację, powoduje to odpowiedź blokującą. – flubba

3

Wystarczy dołączyć map:

WS.url("http://"+domain+url+"?"+params+"&auth_signature="+signatureEncoded).post(body).map(_) 
+0

dzięki za odpowiedzi, można wyjaśnić, dlaczego to działa? Chodzi mi o to, jaka jest wartość wydobyta z przyszłości? – flubba

3

Zakładając, że nie chcesz tworzyć aplikacji blokującej, twoja metoda powinna również zwrócić wartość Future[ws.Response]. Niech twoja przyszłość spieprzy się z kontrolerem, gdzie zwrócisz AsyncResult używając Async { ... } i pozwól Playowi zająć się resztą.

Controller

def webServiceResult = Action { implicit request => 
    Async { 
    // ... your logic 
    trigger(channel, event, message).map { response => 
     // Do something with the response, e.g. convert to Json 
    } 
    } 
} 
+0

Nie mogę znaleźć Async {} w 2.1 api: http://www.playframework.com/ documentation/api/2.1.0/scala/index.html # package – flubba

+0

której biblioteki mogę zaimportować do korzystania z Async? Czym różni się od AsyncResult? I obecnie importować te dwa, które mogą być związane z: 'importu scala.concurrent._ importu play.api.libs.concurrent.Execution.Implicits._' dzięki – flubba

+0

To tutaj https://github.com/ playframework/Play20/blob/master/framework/src/play/src/main/scala/play/api/mvc/Results.scala # L669. Wystarczy zaimportować 'play.api.mvc._' –

Powiązane problemy