试图理解 Scala enumerator/iteratees

Trying to understand Scala enumerator/iteratees

我是 Scala 和 Play! 的新手,但在使用 Django 和 Python 构建 Web 应用程序以及一般编程方面有一定的经验。

我一直在做自己的练习以尝试提高我的理解力 - 只需从数据库中提取一些记录并将它们输出为 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)
  }
}

我有两个主要问题:

还有几个子问题,以帮助我理解:

非常感谢您的回答,我以为我已经掌握了窍门,但显然还没有!

How do i signal that the input is complete from the Enumerator callback?

你return一个Future(None).

How do I get the final result out of the Future to return from the controller view?

您可以使用 Action.async (doc):

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

Why do I need to wrap my object in Some() when it's already in a Future? What exactly does Some() represent?

Future表示获取下一个元素的(可能是异步的)处理。 Option表示下一个元素的可用性:Some(x)如果另一个元素可用,None如果枚举完成。