我是play2.0-Scala-beginner,必须调用多个Webservices来生成HTML页面。
在阅读The Play WS API页面和非常有趣article from Sadek Drobi之后,我仍然不确定实现此目标的最佳方法是什么。
这篇文章展示了一些我不完全理解为Play初学者的代码片段。
第4页的图2:
val response: Either[Response,Response] =
WS.url("http://someservice.com/post/123/comments").focusOnOk
val responseOrUndesired: Either[Result,Response] = response.left.map {
case Status(4,0,4) => NotFound
case Status(4,0,3) => NotAuthorized
case _ => InternalServerError
}
val comments: Either[Result,List[Comment]] =
responseOrUndesired.right.map(r => r.json.as[List[Comment]])
// in the controller
comment.fold(identity, cs => Ok(html.showComments(cs)))
fold
的最后一行是做什么的? comment
应comments
吗?我没有在Async
块中对最后一个语句进行分组吗?
图4显示了如何将多个IO调用与单个for
- 表达式组合在一起:
for {
profile <- profilePromise
events <- attachedEventsPromise
articles <- topArticlesPromise
} yield Json.obj(
"profile" -> profile,
"events" -> events,
"articles" -> articles )
}
// in the controller
def showInfo(...) = Action { rq =>
Async {
actorInfo(...).map(info => Ok(info))
}
}
如何使用此代码段? (在for-expression之后,我对额外的}
感到有点困惑。)
我应该写这样的东西吗?
var actorInfo = for { // Model
profile <- profilePromise
events <- attachedEventsPromise
articles <- topArticlesPromise
} yield Json.obj(
"profile" -> profile,
"events" -> events,
"articles" -> articles )
def showInfo = Action { rq => // Controller
Async {
actorInfo.map(info => Ok(info))
}
}
结合图2和图4中的片段(错误处理+ IO非阻塞调用的组合)的最佳方法是什么? (例如,如果任何被调用的web服务产生错误404,我想生成错误404状态代码。)
也许有人知道在播放框架中调用webservices的完整示例(在播放Sample应用程序或其他任何地方都找不到示例)。
答案 0 :(得分:2)
我必须说在图2中显示的示例中该文章是错误的。方法focusOnOk
在Play 2.0中不存在。我假设该文章的作者使用了Play 2的预发布版本。
关于comment
,是的,它应该是comments
。声明中的fold
正在Either
上运行。它需要2个函数作为参数。第一个是如果是左值则应用的函数。第二个是如果它是正确值则应用的函数。可在此处找到更详细的说明:http://daily-scala.blogspot.com/2009/11/either.html
那么这条线的作用是什么。如果我有一个左值(这意味着我得到了一个不需要的响应),请应用内置的identity
函数,该函数只返回值。如果它具有正确的值(这意味着我得到了一个OK响应),请创建一个以某种方式显示注释的新结果。
关于Async
,它实际上不是异步的。 focusOnOk
是一个阻塞函数(来自Play 1.x的旧Java时代的残余)。但请记住,这不是有效的Play 2代码。
对于图4,尾随}
实际上是因为它是图3中的部分替代。而不是许多承诺flatMap
。您可以改为for comprehension。另外,我认为它应该是userInfo(...).map
而不是actorInfo(...).map
。
您链接到的Play documentation实际上已经向您展示了一个完整的示例。
def feedTitle(feedUrl: String) = Action {
Async {
WS.url(feedUrl).get().map { response =>
Ok("Feed title: " + (response.json \ "title").as[String])
}
}
}
将获取feedUrl上的任何内容,并map
使用response
对status
字段执行某些操作,您可以检查该字段是否为404或其他内容
为此,您链接文章的图3和图4应该为您提供一个起点。所以你有类似的东西,
def getInfo(...) : Promise[String] = {
val profilePromise = WS.url(...).get()
val attachedEventsPromise = WS.url(...).get()
val topArticlesPromise = WS.url(...).get()
for {
profile <- profilePromise
events <- attachedEventsPromise
articles <- topArticlesPromise
} yield {
// or return whatever you want
// remember to change String to something else in the return type
profile.name
}
}
def showInfo(...) = Action { rq =>
Async {
getInfo(...).map { info =>
// convert your info to a Result
Ok(info)
}
}
}