在Play Framework 2.2中使用非异步操作有什么好处吗?

Yog*_*ter 5 playframework playframework-2.2

播放2.2文档指出:

由于Play的工作方式,动作代码必须尽可能快(即非阻塞).那么如果我们还不能生成它,我们应该返回什么呢?回应是未来的结果!

未来[结果]最终将使用Result类型的值进行兑换.通过给出Future [Result]而不是普通Result,我们可以快速生成结果而不会阻塞.然后,Play将在兑换承诺后立即提供此结果.

在等待响应时将阻止Web客户端,但服务器上不会阻止任何内容,并且可以使用服务器资源为其他客户端提供服务.

创建返回Future的操作,Action.async而不是Action.apply正常的非异步操作.

有非异步操作有什么好处吗?令我感到震惊的是,确保我的所有动作都不会阻止的最佳方法是声明所有动作都使用Action.async.

实际上,根据Play Framework 2.3文档,它在Play 2.3中看起来像所有操作都是异步的:

注意:Action.apply和Action.async都创建以相同方式在内部处理的Action对象.有一种Action是异步的,而不是两种(同步的和异步的)..async构建器只是简化基于返回Future的API创建操作的工具,这使得编写非阻塞代码变得更加容易.

Mic*_*jac 12

仅仅因为你可能会使用Action.async,并不会自动意味着你没有阻止.这完全取决于您是否使用阻止API.

Play 2.2似乎与Play 2.3的工作方式相同.除了他们的签名之外,Action.apply和之间并没有真正的区别Action.async.Action.async期望一些返回a的代码块Future[Result],同时Action.apply期望返回一个代码块Result.通过简单地调用Action.apply将其block: => Result转换Future[Result]Future.successful(block).(在打电话之前还有一些工作要做Future.successful,但这是它的要点.)

因此,每个用例都归结为您正在使用的API.例如JDBC vs ScalikeJDBC-async,阻塞与非阻塞数据库API.假设您从数据库中提取用户并将其作为json发送回客户端.

典型的JDBC支持函数的签名可能如下所示(忽略简化失败):

def read(id: Long): User
Run Code Online (Sandbox Code Playgroud)

您的控制器功能可能如下所示:

def read(id: Long) = Action {
    Ok(Json.toJson(User.read(id))
}
Run Code Online (Sandbox Code Playgroud)

这大致等同于Action.apply:

def read(id: Long) = Action.async {
    Future.successful(Ok(Json.toJson(User.read(id)))
}
Run Code Online (Sandbox Code Playgroud)

User.read 然而,仍然是一个阻塞的JDBC调用,所以这并不比以前更好.

现在让我们假设我们使用的异步数据库调用如下所示:

def read(id: Long): Future[User]
Run Code Online (Sandbox Code Playgroud)

控制器功能看起来像这样:

def read(id: Long) = Action.async {
    User.read(id).map(user => Ok(Json.toJson(user)))
}
Run Code Online (Sandbox Code Playgroud)

可以把它想象成使用返回Futures的API的帮手.真正的好处来自这些API的实际异步实现.如果您遇到阻塞API(可能是JDBC),还有其他方法可以对其进行管理.Play邮件列表上的这个主题是关于这个主题的一个很好的读物:https://groups.google.com/forum/#!topic / play-frame/WWQ0HeLDOjg