异步等待 Playframework (2.4-M3) 和 Slick (3.0.0-RC3) 中的数据库值
Asynchronous wait for database-value in Playframework (2.4-M3) and Slick (3.0.0-RC3)
我想让我的应用程序尽可能异步。现在我有了这个存储库:
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}" 这样调用 url 时,我想检查给定的语言(代码)是否确实存在。比如,如果该站点没有法语版 (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 的 Playframeworks 异步文档 (https://www.playframework.com/documentation/2.3.6/ScalaAsync),但我无法真正让它按预期工作。
感谢任何意见!
试试这个,
Action.async {
val lang:Future[Option[Language]] = languageRepository.find(language)
lang.map {l => l.map{_ => Ok("Yay") }.getOrElse(NotFound("Oh no!"))
}
首先,我假设如果有一种语言可能不存在,那么 languageRepository.find(language)
应该 return 和 Language
的 Option
。将 Future[Language]
更改为 Future[Result]
并使用 Action.async
而不是 Action
现在进行一些解释,Action
取一个块,其结果应该是 Result
。然而,你得到的却是Future[Option[Language]]
。 Play 为需要 Future[Result]
的 Action
提供了 async
方法,它负责完成请求。
因此,您需要将 Future[Option[Language]]
转换为 Future[Result]
。
lang.map {l => l.map{_ => Ok("Yay") }.getOrElse(NotFound("Oh no!"))
我们映射 lang,如果 Option[Language]
不是 None
那么我们将其转换为 Ok("yay")
否则我们将其转换为 NotFound
甚至,如果没有得到Option[Language]
,思路还是一样的。将 Future[Language]
转换为 Future[Result]
并使用 Action.async
而不是 Action
在您的数据库查询中,不要使用 .head,而是使用 .headOption。这样你的 return 类型将是 Future [Option [x]]
在你的控制器中你可以做这样的事情
Lang.map { case Some (x) => Ok (x)
case None => 404 ( "not found ")
}
我想让我的应用程序尽可能异步。现在我有了这个存储库:
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}" 这样调用 url 时,我想检查给定的语言(代码)是否确实存在。比如,如果该站点没有法语版 (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 的 Playframeworks 异步文档 (https://www.playframework.com/documentation/2.3.6/ScalaAsync),但我无法真正让它按预期工作。
感谢任何意见!
试试这个,
Action.async {
val lang:Future[Option[Language]] = languageRepository.find(language)
lang.map {l => l.map{_ => Ok("Yay") }.getOrElse(NotFound("Oh no!"))
}
首先,我假设如果有一种语言可能不存在,那么 languageRepository.find(language)
应该 return 和 Language
的 Option
。将 Future[Language]
更改为 Future[Result]
并使用 Action.async
而不是 Action
现在进行一些解释,Action
取一个块,其结果应该是 Result
。然而,你得到的却是Future[Option[Language]]
。 Play 为需要 Future[Result]
的 Action
提供了 async
方法,它负责完成请求。
因此,您需要将 Future[Option[Language]]
转换为 Future[Result]
。
lang.map {l => l.map{_ => Ok("Yay") }.getOrElse(NotFound("Oh no!"))
我们映射 lang,如果 Option[Language]
不是 None
那么我们将其转换为 Ok("yay")
否则我们将其转换为 NotFound
甚至,如果没有得到Option[Language]
,思路还是一样的。将 Future[Language]
转换为 Future[Result]
并使用 Action.async
而不是 Action
在您的数据库查询中,不要使用 .head,而是使用 .headOption。这样你的 return 类型将是 Future [Option [x]]
在你的控制器中你可以做这样的事情
Lang.map { case Some (x) => Ok (x)
case None => 404 ( "not found ")
}