2016-09-26 8 views
0

私はScalaとPlay!を初めて使っていますが、DjangoとPythonを使用したWebアプリケーションの構築と一般的なプログラミングの経験があります。Scala enumerator/iterateesを理解しようとしています

私は自分の理解を向上させるために自分自身の演習を行っています。データベースからレコードをいくつか取り出し、JSON配列として出力するだけです。私はこれを行うためにEnumarator/Iteratee機能を使用しようとしています。

私のコードは次のとおりです。

TestObjectController.scala:

def index = Action { 
    db.withConnection { conn=> 
     val stmt = conn.createStatement() 
     val result = stmt.executeQuery("select * from datatable") 

     logger.debug(result.toString) 
     val resultEnum:Enumerator[TestDataObject] = Enumerator.generateM { 
     logger.debug("called enumerator") 
     result.next() match { 
      case true => 
      val obj = TestDataObject(result.getString("name"), result.getString("object_type"), 
       result.getString("quantity").toInt, result.getString("cost").toFloat) 
      logger.info(obj.toJsonString) 
      Future(Some(obj)) 
      case false => 
      logger.warn("reached end of iteration") 
      stmt.close() 
      null 
     } 
     } 

     val consume:Iteratee[TestDataObject,Seq[TestDataObject]] = { 
     Iteratee.fold[TestDataObject,Seq[TestDataObject]](Seq.empty[TestDataObject]) { (result,chunk) => result :+ chunk } 
     } 

     val newIteree = Iteratee.flatten(resultEnum(consume)) 
     val eventuallyResult:Future[Seq[TestDataObject]] = newIteree.run 
     eventuallyResult.onSuccess { case x=> println(x)} 
     Ok("") 

    } 
    } 

TestDataObject.scala:私はどのように

  • package models 
    
    case class TestDataObject (name: String, objtype: String, quantity: Int, cost: Float){ 
        def toJsonString: String = { 
        val mapper = new ObjectMapper() 
        mapper.registerModule(DefaultScalaModule) 
        mapper.writeValueAsString(this) 
        } 
    } 
    

    を私は2つの主要な質問がありますそれを知らせる入力は列挙子のコールバックから完了していますか?ドキュメントでは、 "このメソッドは、この列挙子が適用されるたびに呼び出されるコールバック関数e:=> Future [Option [E]]を取ります。何らかの入力を行う準備ができています。私はそれが間違ったタイプなので、私が見つけたどんな種類のEOFも渡すことができません。将来のラッピングは助けになりませんが、本能的に私はそれが正しいアプローチであるかどうかはわかりません。

  • 未来の最終結果をコントローラビューから返すにはどうすればよいですか?私の理解は、サブスレッドが完了するのを待つために主スレッドを一時的に休止する必要があるということですが、私が見た唯一の例と、将来のクラスで見つけたものだけがonSuccessコールバックです。それをビューから返しますか?すべての入力が消費されるまでIteratee.runブロックしますか?

だけでなく、サブの質問のカップル、私の理解を助けるために:それは将来にすでにだとき

  • は、なぜ私は)いくつかの(で私のオブジェクトをラップする必要がありますか? Some()は正確に何を表していますか?
  • 初めてコードを実行すると、logger.infoから記録された単一のレコードが取得され、「到達済みの終了」というレポートが表示されます。同じセッションでの後続の実行では何も呼び出されません。私はその声明を締めくくっています。なぜ2回目に結果が得られないのですか?私はループの正しい終了を知らせる方法がわからないので、無期限にループすることを期待していました。

これまでのお返事はありがとうございました。

答えて

0

どのように入力が列挙子コールバックから完了したことを通知しますか?

あなたはFuture(None)を返します。

未来の最終結果をコントローラビューから返すにはどうすればよいですか?

を使用できAction.asyncdoc):

def index = Action.async { 
    db.withConnection { conn=> 
    ... 
    val eventuallyResult:Future[Seq[TestDataObject]] = newIteree.run 
    eventuallyResult map { data => 
     OK(...) 
    } 
    } 
} 

なぜ私は私のオブジェクトをラップする必要がありますいくつかの()それは将来にすでにだとき? Some()は正確に何を表していますか?

Futureは、次の要素を取得する(潜在的には非同期の)処理を表します。 Optionは、次の要素の可用性を表します。別の要素が使用可能であればSome(x)、列挙が完了するとNoneです。

+0

すばらしい答えに感謝します。私はAction.asyncについて完全に忘れていました。それは私が持っていたいくつかの混乱を解消しました。私は今、ちょうど非常に奇妙なものを持っています - Action.asyncを使用すると、テーブル内の4つの結果が返されます。私がOk(Await.result(finallyResult、60 seconds))を標準的なActionの最終行として使用すると、4つすべてを取得します。なぜ地球上でこれが事実だろうか? –

+0

残念ながら私はその理由を知ることができません。あなたは "反復の終わりに達しました"というメッセージを受け取りますか? – devkat

+0

はい、私は "反復の終了に達しました"という直後に "列挙子が呼び出され"ます。私はここで補足的な質問としてこれを尋ねました:http://stackoverflow.com/questions/39728486/strange-enumerator-iteratee-future-behaviour-when-querying-database、あなたが見て時間があればそれを感謝します! –

関連する問題