4

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 と Promise.timeout から簡単に Promise を取得できますか?

ありがとう :)

4

1 に答える 1

4

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!"メッセージに煩わされることはありませんが、正確に何をしているのかによっては、それは適切でない場合があります。

于 2012-08-05T16:04:04.237 に答える