Because of the way Play works, the action code must be as fast as possible (ie. non blocking). So what should we return as result if we are not yet able to generate it? The response is a future result!
A Future[Result] will eventually be redeemed with a value of type Result. By giving a Future[Result] instead of a normal Result, we are able to quickly generate the result without blocking. Then, Play will serve this result as soon as the promise is redeemed.
The web client will be blocked while waiting for the response, but nothing will be blocked on the server, and server resources can be used to serve other clients.
创建返回 Future 的操作
Action.async
,而不是 Action.apply
对于正常的非异步操作。使用非异步操作有什么好处吗?令我震惊的是,确保我的任何操作都不会被阻止的最佳方法是使用
Action.async
声明所有操作。 .事实上,根据 Play Framework 2.3 documentation看起来在 Play 2.3 中所有 Action 都是异步的:
Note: Both Action.apply and Action.async create Action objects that are handled internally in the same way. There is a single kind of Action, which is asynchronous, and not two kinds (a synchronous one and an asynchronous one). The .async builder is just a facility to simplify creating actions based on APIs that return a Future, which makes it easier to write non-blocking code.
最佳答案
只是因为你可能会使用 Action.async
,并不自动意味着您没有阻止。这完全取决于您是否使用阻塞 API。
Play 2.2 似乎以这种方式与 Play 2.3 工作方式相同。 Action.apply
之间没有真正的区别和 Action.async
, 除了他们的签名。 Action.async
期望一些返回 Future[Result]
的代码块, 而 Action.apply
期望返回 Result
的代码块. Action.apply
转换 block: => Result
进入 Future[Result]
只需调用 Future.successful(block)
. (在调用 Future.successful
之前还有一些工作要做,但这是它的要点。)
因此,每个用例都归结为您正在使用的 API。例如 JDBC 与 ScalikeJDBC-async ,阻塞与非阻塞数据库 API。假设您正在从数据库中获取用户并将其作为 json 发送回客户端。
典型的 JDBC 支持函数的签名可能如下所示(忽略简化失败):
def read(id: Long): User
您的 Controller 功能可能如下所示:
def read(id: Long) = Action {
Ok(Json.toJson(User.read(id))
}
这大致相当于
Action.apply
做:def read(id: Long) = Action.async {
Future.successful(Ok(Json.toJson(User.read(id)))
}
User.read
然而,它仍然是一个阻塞的 JDBC 调用,所以这并不比以前更好。现在假设我们正在使用如下所示的异步 DB 调用:
def read(id: Long): Future[User]
Controller 函数看起来像这样:
def read(id: Long) = Action.async {
User.read(id).map(user => Ok(Json.toJson(user)))
}
可以将其更多地视为使用返回
Future
的 API 的助手。 s。真正的好处来自这些 API 的实际异步实现。如果您遇到阻塞 API(可能是 JDBC),还有其他方法可以管理它。 Play 邮件列表上的这个帖子是一个很好的阅读主题:https://groups.google.com/forum/#!topic/play-framework/WWQ0HeLDOjg
关于playframework - 在 Play Framework 2.2 中使用非异步操作有什么好处吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23997418/