我正在阅读来自 playframework 的一些 http webservice API,链接如下。
我无法理解这种嵌套如何与平面图一起使用。
有人可以给我一些如何破解这一大块函数调用的提示吗?
来自 http://www.playframework.com/documentation/2.2.x/JavaWS
合成结果
如果您想按顺序拨打多个电话,
这可以使用 flatMap 来实现:
public static Promise<Result> index() {
final Promise<Result> resultPromise = WS.url(feedUrl).get().flatMap(
new Function<WS.Response, Promise<Result>>() {
public Promise<Result> apply(WS.Response response) {
return WS.url(response.asJson().findPath("commentsUrl").asText()).get().map(
new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
return ok("Number of comments: " + response.asJson().findPath("count").asInt());
}
}
);
}
}
);
return resultPromise;
}
flatMap
和 map
是常见的 Scala(或更一般地说,函数式编程)函数。它们都接受 function 作为参数。为了将 Play WS API 转换为 Java(以及几乎所有其他内容),需要用 Java 重新实现 Scala 的函数类型,以便您可以充分利用 WS 库。这里的完成方式与 Scala 编译器类似。 Function<A,B>
是一个抽象类型,需要 apply
方法。 apply
的参数是函数的参数,apply
的返回类型是函数的返回类型。
如果你的Java中有这个函数:
public String int2String(Integer integer) {
return integer.toString();
}
这相当于:
new Function<Integer, String>() {
public String apply(Integer integer) {
return integer.toString();
}
}
让我们从只有一个 WS 调用的情况开始更简单。
WS.url(...).get()
返回 Promise<WS.Response>
。 Promise
是 promised 值的容器类。为了处理它包含(或最终包含)的值,我们需要使用 map
函数。对于 Promise<WS.Response>
,map
将接受 Function<WS.Response, T>
作为参数,其中 T
是要将响应映射到的类型。
作为示例,让我们定义一个
Function
,它将仅返回 Play HTTP 中 WS.Response
的主体 Result
:
Function<WS.Response, Result> echo = new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
return ok(response.asText());
}
}
现在让我们在控制器的 WS 调用中使用这个
Function
:
public static Promise<Result> index() {
final Promise<Result> resultPromise = WS.url("http://google.com").get().map(echo);
return resultPromise;
}
一旦满足
Promise
,之前定义的echo
函数将在map
内部执行,返回Promise<Result>
。前面的两段代码也可以这样写(用匿名函数合二为一):
public static Promise<Result> index() {
final Promise<Result> resultPromise = WS.url("http://google.com").get().map(
new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
return ok(response.asText());
}
}
);
return resultPromise;
}
作为一个粗略的例子,假设我们需要进行两次 WS 调用。第二个 WS 调用将取决于第一个 WS 调用。也许第一个调用会给我们一些 URL,我们将使用它来进行第二个 WS 调用。
这就是
flatMap
出现的地方。我们需要两个函数来完成这项任务。第一个函数是传递给 flatMap
的函数,它将在收到第一个 WS.Response
时执行。第一个函数将使用第一个响应进行第二个 WS 调用,该调用返回另一个必须映射才能获得最终结果的 Promise<WS.Response>
。因此,我们使用第二个函数将 map
转换为我们的 WS.Response
。那么发生了什么?如果我们在这两种情况下都使用
Result
而不是
map
,事件链将如下所示:第一个
flatMap
返回一个
get()
,然后我们将包含的Promise<WS.Response>
返回到map
。然而,这会给我们留下一个WS.Response
,这不是很理想。在外部函数中使用 Promise<Result>
会将 Promise<Promise<WS.Response>>
展平为单个 flatMap
。同样,如果您进行 3 个或更多嵌套调用,您会将每个结果 Promise
传递给一个内部函数,并且在外部层只有一个 Promise<Result>
以在最后将所有内容展平。这一切在 Scala 中当然看起来更漂亮。