当您在控制器中使用 await 时,它会增强字节码以将单个方法分成两个线程。这很酷,但绝对是 Play1 的“黑魔法”之一。但是,这是 Play 经常表现得很奇怪并且需要重新启动(或者如您所见,需要更改一些代码)的地方 - 另一个可能表现得很奇怪的地方是当您更改 Model 类时。
http://www.playframework.com/documentation/1.2.5/asynchronous#SuspendingHTTPrequests
为了更容易处理异步代码,我们引入了延续。延续允许您的代码透明地暂停和恢复。因此,您以非常必要的方式编写代码,例如:
public static void computeSomething() { Promise delayResult = veryLongComputation(...); 字符串结果 = 等待(延迟结果);渲染(结果);}
实际上,在这里,您的代码将分 2 步执行,分 2 个不同的线程执行。但正如您所见,它对您的应用程序代码非常透明。
使用 await(...) 和延续,您可以编写一个循环:
public static void loopWithoutBlocking() {
for(int i=0; i<=10; i++) {
Logger.info(i);
await("1s");
}
renderText("Loop finished"); }
并且仅使用 1 个线程(这是开发模式下的默认设置)来处理请求,Play 能够同时为多个请求同时运行这些循环。
要回复您的评论:
public static void generatePDF(Long reportId) {
Promise<InputStream> pdf = new ReportAsPDFJob(report).now();
InputStream pdfStream = await(pdf);
renderBinary(pdfStream);
而 ReportAsPDFJob 只是一个覆盖 doJobWithResult 的 play Job 类 - 所以它返回对象。有关工作的更多信息,请参阅http://www.playframework.com/documentation/1.2.5/jobs。
调用job.now()
返回一个未来/承诺,您可以像这样使用它:await(job.now())