在 Play Framework 2.2 中使用非异步操作有什么好处吗? [英] Are there any benefits in using non-async actions in Play Framework 2.2?

查看:12
本文介绍了在 Play Framework 2.2 中使用非异步操作有什么好处吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Play 2.2 文档指出:

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

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!

一个 Future[Result] 最终会被赎回一个 Result 类型的值.通过提供 Future[Result] 而不是普通的 Result,我们能够快速生成结果而不会阻塞.然后,Play 将在兑现承诺后立即提供此结果.

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.

Web 客户端在等待响应时会被阻塞,但服务器上不会被阻塞,并且服务器资源可以用于为其他客户端提供服务.

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 用于正常的非异步操作.

Actions that return a Future are created Action.async, as opposed to Action.apply for normal, non-async actions.

非异步操作有什么好处吗?让我印象深刻的是,确保我的任何操作都不会被阻塞的最佳方法是使用 Action.async 声明所有这些操作.

Is there any benefit on having non-async Actions? It strikes me that the best way to ensure that none of my Actions are going to block is to declare all of them using Action.async.

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

In fact, according to the Play Framework 2.3 documentation it looks like in Play 2.3 all actions are async:

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

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.

Just because you might use Action.async, doesn't automatically mean you're not blocking. It all depends on whether you're using blocking API or not.

Play 2.2 似乎与 Play 2.3 以这种方式工作.除了签名之外,Action.applyAction.async 之间没有真正的区别.Action.async 需要返回 Future[Result] 的代码块,而 Action.apply 需要返回 Future[Result] 的代码块代码>结果.Action.apply 转换 block: =>;只需调用Future.successful(block),即可将Result转化为Future[Result].(在调用 Future.successful 之前还有一些工作要做,但这是它的要点.)

Play 2.2 seems to work the same way as Play 2.3 in this manner. There isn't really a difference between Action.apply and Action.async, other than their signatures. Action.async expects some block of code that returns a Future[Result], while Action.apply expects a block of code that returns a Result. Action.apply converts that block: => Result into Future[Result] by simply calling Future.successful(block). (There is a little more work that goes on before calling Future.successful, but this is the gist of it.)

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

So the use cases for each boil down to the API you're using. For example JDBC vs ScalikeJDBC-async, blocking vs. non-blocking database APIs. Let's say you're fetching a user from the database and sending it back to the client as json.

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

The signature of a typical JDBC-backed function might look like this (ignoring failures to simplify):

def read(id: Long): User

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

Your controller function might then look like this:

def read(id: Long) = Action {
    Ok(Json.toJson(User.read(id))
}

这大致相当于 Action.apply 所做的:

This is roughly equivalent to what Action.apply does:

def read(id: Long) = Action.async {
    Future.successful(Ok(Json.toJson(User.read(id)))
}

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

User.read is still a blocking JDBC call, however, so this is no better than before.

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

Now let's say we're using an asynchronous DB call that looks something like this:

def read(id: Long): Future[User]

控制器函数看起来像这样:

The controller function would look something like this:

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

将其更多地视为使用返回 Future 的 API 的助手.真正的好处来自这些 API 的实际异步实现.如果您坚持阻塞 API(可能是 JDBC),还有其他方法可以管理它.Play 邮件列表上的此主题很好地阅读了该主题:https://groups.google.com/forum/#!topic/play-framework/WWQ0HeLDOjg

Think of it as more of a helper for using APIs that return Futures. The real benefits come from actual asynchronous implementations of those APIs. If you're stuck with blocking API (probably JDBC), there are other ways to manage that as well. This thread on the Play mailing list is a good read on the subject: https://groups.google.com/forum/#!topic/play-framework/WWQ0HeLDOjg

这篇关于在 Play Framework 2.2 中使用非异步操作有什么好处吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆