我在Scala中编写了一个Play 2.3.2应用程序。 我使用reactivemongo驱动程序访问mongodb数据库。 我已经编写了该查询db以获取数据库中最常用的标记。 此方法是Action.async,并按以下方式实现:
def max = Action.async { request =>
var max: Int = 0
var tagFound: Tag = null
//obtain all the tags in the db.
val futureTags: Future[List[Tag]] = Tags.all.toList
futureTags map{ (tags: List[Tag]) =>
tags map { (tag: Tag) =>
//create the tag String
val tagName = tag.category + ":" + tag.attr
//search in the db the documents where tags.tag == tag.
val futureRequests : Future[List[recommendationsystem.models.Request]]= Requests.find(Json.obj("tags.tag" -> tagName)).toList
futureRequests map { (requests: List[recommendationsystem.models.Request]) =>
//get the numbers of documents matching the tag
val number: Int= requests.size
if(number > max) {
max = number
tagFound = tag
}
println(max)
}
}
val jsonObject = if(max > 0) Json.obj("tag" -> tagFound, "occurencies" -> max) else Json.obj("tag" -> "NoOne", "occurencies" -> 0)
Ok(jsonObject)
}
}
但这种方法的行为不确定,有什么不对?
我无法理解val jsonObject = if(max > 0) Json.obj("tag" -> tagFound, "occurencies" -> max) else Json.obj("tag" -> "NoOne", "occurencies" -> 0)
Ok(jsonObject)
}
执行异步,不要等待tags map
语句完成。
答案 0 :(得分:1)
我发现您的代码存在一些问题:
这是一段重写的代码,我没有编译它,但你可以知道它应该如何工作:
def max = Action.async { request =>
Tags.all.toList.flatMap { case tags =>
val xs = tags map { case tag =>
val tagName = tag.category + ":" + tag.attr
Requests.find(Json.obj("tags.tag" -> tagName)).toList.map (requests => (tag, requests.size) )
}
val f = Future.sequence(xs)
f.map { case ys =>
val res = ys.foldLeft(Option.empty[(Tag, Int)]) {
case (Some((maxTag, maxOcc)), (tag, occ)) if occ > maxOcc => Some(tag, occ)
case (s@Some(_), _) => s
case (None, (tag, occ)) => Some(tag, occ)
}
val jsonObject = res.map { case (tag, maxOcc) =>
Json.obj("tag" -> tagFound, "occurencies" -> maxOcc)
} getOrElse {
Json.obj("tag" -> "NoOne", "occurencies" -> 0)
}
Ok(jsonObject)
}
}
}
答案 1 :(得分:0)
Future.map
会返回另一个Future
- 它不会立即运行。致电f.map(...)
后,f
可能尚未完成。
如果您要在Future
完成之前阻止,请使用Future.get
(这样您就可以f.map(...).get
,但在这种情况下您也可以执行f.get
并执行此操作对该值的计算 - 当然这不是非阻塞的)。如果您想将多个异步计算链接在一起,可以使用flatMap
和sequence
,并且在@ vitalii的答案中应尽量避免使用var
s。
-Ywarn-value-discard
编译器标志可以在您丢弃值时向您发出警告,这通常表示该程序存在问题。