play异步http编程
1.处理异步结果
- 使控制器异步
在内部,Play框架从下到上是异步的。Play以异步的、非阻塞的方式处理每个请求。
- 创建非阻塞操作
一个Future
[Result
]最终将会得到一个类型结果的值。通过给出一个Future[Result]而不是一个普通的结果,我们能够快速生成结果而不阻塞。
当Future
被完成
时,play
就会服务于result
。
使用Future只是其中的一半!如果您调用了一个阻塞的API,如JDBC,那么您仍然需要使用不同的executor运行您的ExecutionStage,
以将它从Play的呈现线程池中移开。你可以通过创建一个子类play.api.libs.concurrent。使用自定义dispatcher引用的CustomExecutionContext。
import play.api.libs.concurrent.CustomExecutionContext
trait MyExecutionContext extends ExecutionContext
class MyExecutionContextImpl @Inject()(system: ActorSystem)
extends CustomExecutionContext(system, "my.executor") with MyExecutionContext
class HomeController @Inject()(myExecutionContext: MyExecutionContext, val controllerComponents: ControllerComponents) extends BaseController {
def index = Action.async {
Future {
// Call some blocking API
Ok("result of blocking call")
}(myExecutionContext)
}
}
- 如何创造Future[Result]
所有的Play的异步API调用都给了你一个Future
。
val futurePIValue: Future[Double] = computePIAsynchronously()
val futureResult: Future[Result] = futurePIValue.map { pi =>
Ok("PI value computed: " + pi)
}
- 返回future
用Action.async来返回异步future。
def index = Action.async {
val futureInt = scala.concurrent.Future { intensiveComputation() }
futureInt.map(i => Ok("Got result: " + i))
}
- 默认情况下,操作是异步的
def echo = Action { request =>
Ok("Got request [" + request + "]")
}
- 处理超时
使用play.api.libs.concurrent.Futures类来设置超时。
import scala.concurrent.duration._
import play.api.libs.concurrent.Futures._
def index = Action.async {
// futures instance implicit here
intensiveComputation().withTimeout(1.seconds).map { i =>
Ok("Got result: " + i)
}.recover {
case e: TimeoutException =>
InternalServerError("timeout")
}
}