我希望尽可能保持我的应用程序异步。现在我有了这个存储库:
object LanguageRepository extends LanguageRepositoryTrait
{
private val languages = TableQuery[Languages]
private def db:Database = Database.forDataSource(DB.getDataSource())
private def filterQuery(id: Long): Query[Languages, Language, Seq] = languages.filter(_.id === id)
private def filterCode(code: String): Query[Languages, Language, Seq] = languages.filter(_.code === code)
private def all() : Query[Languages, Language, Seq] = languages
override def find(id: Long): Future[Language] =
{
try db.run(filterQuery(id).result.head)
finally db.close()
}
override def find(code: String): Future[Language] =
{
try db.run(filterCode(code).result.head)
finally db.close()
}
override def get(): Future[Seq[Language]] =
{
try db.run(all().result)
finally db.close()
}
}
当我打电话给" domain.tld / {language}"我想检查给定的语言(代码)是否确实存在。比如,如果网站不是法语(fr),我想抛出异常或404。
现在,我的问题是,整个异步的事情非常酷,虽然我确实想要理解它背后的理论,但我现在感到困惑。我的意思是,我希望这是非阻塞的(并且异步,这是我使用Future和async的原因;)
在我的控制器中,我想做类似的事情:
def checkLanguage(language:String) = Action
{
val lang:Future[Language] = languageRepository.find(language)
lang.onComplete
{
case Success(s) = Ok("Yay")
case Failure(f) = 404("Oh no!")
}
}
当然这不起作用,但那是我想要让事情发挥作用的模式。我想等待或推迟网站的呈现,直到它确认给定的语言代码有效或无效。
我查看了2.3.6(https://www.playframework.com/documentation/2.3.6/ScalaAsync)的Playframeworks异步文档,但我无法按照预期的方式工作。
任何意见都赞赏!
答案 0 :(得分:2)
试试这个,
Action.async {
val lang:Future[Option[Language]] = languageRepository.find(language)
lang.map {l => l.map{_ => Ok("Yay") }.getOrElse(NotFound("Oh no!"))
}
首先,我假设如果某种语言不存在,那么languageRepository.find(language)
应该返回Option
Language
。将Future[Language]
更改为Future[Result]
并使用Action.async
代替Action
现在有一些解释,Action
采用一个块,其结果应为Result
。但是,你得到的是Future[Option[Language]]
。 Play为需要async
的{{1}}提供Action
方法,并负责完成请求。
因此,您需要将Future[Result]
转换为Future[Option[Language]]
。
Future[Result]
如果 lang.map {l => l.map{_ => Ok("Yay") }.getOrElse(NotFound("Oh no!"))
不是Option[Language]
,我们会映射到lang,然后我们会将其转换为None
,否则我们会将其转换为Ok("yay")
即使如果你没有得到NotFound
,这个想法仍然是一样的。将Option[Language]
转换为Future[Language]
并使用Future[Result]
代替Action.async
答案 1 :(得分:1)
从您的数据库查询中不要使用.head而是使用.headOption。那样你的返回类型将是Future [Option [x]]
在你的控制器你可以做这样的事情
Lang.map { case Some (x) => Ok (x)
case None => 404 ( "not found ")
}