Лучший способ сделать периодический вызов WS, чтобы кормить Enumerator с Play2/Scala?

Я использую шаблон Enumerator для получения некоторых твитов каждую секунду с помощью WS.url

Enumerator.fromCallback[String](() => 
        Promise.timeout(WS.url("http://search.twitter.com/search.json?q="+query+"&rpp=1").get().map { response =>
            val tweets = response.json \\ "text"
            tweets match {
                case Nil => "Nothing found!"
                case head :: tail => query + " : " + head.as[String]
            }
        }.map(Some.apply).value.get, 1000 milliseconds)
  )

Моя проблема в том, что

Enumerator.fromCallback[String]() 

ждет

Promise[Option[String]]

Поскольку WS.url(...). Get возвращает Promise, и поскольку я использую Promise.timeout для повторного запуска вызова каждую секунду,

у меня есть

Promise[Promise[Option[String]]] 

Поэтому я должен использовать value.get, чтобы иметь хороший тип, поэтому он не выглядит очень чистым для асинхронного аспекта.

Этот код работает, но мой вопрос: есть ли лучший способ, более элегантный, для достижения этого? Могу ли я легко получить Обещание от другого Обещания и Promise.timeout?

Спасибо:)

1 ответ

Решение

Promise это монада, и вообще, когда вы оказываетесь с вложенной монадой, вы хотите flatMap где-то там В вашем случае что-то вроде этого должно работать:

import akka.util.duration._
import play.api.libs.concurrent._
import play.api.libs.iteratee._
import play.api.libs.ws._

val query = "test"
val url = WS.url("http://search.twitter.com/search.json?q=" + query + "&rpp=1")

val tweets = Enumerator.fromCallback[String](() => 
  Promise.timeout(url.get, 1000 milliseconds).flatMap(_.map { response =>
    (response.json \\ "text") match {
      case Nil => "Nothing found!"
      case head :: _ => query + " : " + head.as[String]
    }
  }.map(Some.apply))
)

Я бы лично написал это так:

val tweets = Enumerator.fromCallback[String](() => 
  Promise.timeout(url.get, 1000 milliseconds).flatMap(_.map(
    _.json.\\("text").headOption.map(query + " " + _.as[String])
  ))
)

И не суетиться "Nothing found!" сообщение, но в зависимости от того, что именно вы делаете, это может быть неуместно.

Другие вопросы по тегам