【发布时间】:2016-10-03 16:44:26
【问题描述】:
用例实际上是相当典型的。许多 Web 服务使用您在会话开始时检索的授权令牌,您需要在后续请求中将其发回。
我知道我可以这样做:
lazy val myData = {
val request = ws.url("/some/url").withAuth(user, password, WSAuthScheme.BASIC).withHeaders("Accept" -> "application/json")
Await.result(request.get().map{x => x.json }, 120.seconds)
}
感觉不对,因为所有文档都说我们永远不会等待。
是否有 Future/Promise Scala 风格的方式来处理这个问题?
我找到了.onComplete,它允许我在 Promise 完成时运行代码,但是不使用(可变)var 我认为无法将该范围内的值放入 lazy val 中范围不同。即使使用var,也可能存在时间问题——因此可变变量的弊端:)
还有其他方法吗?
【问题讨论】:
-
如果您的目标(不是特定于 PlayWS)是从
Future[T]中获得T,则将其声明为lazy val对我来说没有任何改变:要么您使用Await(有已知的缺点),或者你不能。 -
模式是收集这些数据一次并多次使用——这正是
lazy val所暗示的。我正在尝试翻转事物(首先在我的脑海中),这样一旦收到此值,我就会在.onComplete范围内收集我需要的其余内容并在那里完成处理。考虑到需要做什么以及需要在“哪里”完成(在 Actor 内部),这种方法可能会奏效。 -
您可以将
Future[T]设为lazy val,但不确定它是否真的有用 -
仅供参考:上面的代码在我还无法破译的 Actor 内部造成了某种地狱。如果我使用
Action.sync {...}通过控制器的操作调用该代码,如果运行没有问题。但是,如果我尝试通过计时器任务在 Actor 触发器中调用完全相同的代码,那么代码就会停止运行。我没有被锁定我只是在第一次调用 ws.url() 时得到从悬崖上掉下来的代码。计时器继续像“站点”本身一样运行,但 Actor 似乎从未进行实际的网络调用。还不知道如何克服这个... -
最后一条评论——stackoverflow.com/a/17612613/2162886——显然@Inject 在字段级别不起作用,除非您的类本身被注入。这是可以原谅的,但它不会在失败时尖叫该死的地狱。我有一个完全静默的空指针——没有堆栈跟踪——什么都没有。日子又一次浪费在 Guice 上……
标签: scala playframework-2.0 future ws-client