我遇到一些奇怪的问题,方法是等待(未来的未来)控制器。
每当我在代码中的任何地方添加await行时,一些GenericModel与我放置的位置无关,开始加载错误,我无法访问它们的任何属性。
最奇怪的是,如果我在项目的任何地方更改另一个完全不同的java文件中的某些内容,我会尝试重新编译,并且在那一刻它开始完美运行,直到我再次清理tmp。
答案 0 :(得分:1)
当你在控制器中使用await时,它会进行字节码增强,将单个方法分解为两个线程。这很酷,但绝对是Play1的“黑魔法”技巧之一。但是,这是一个Play常常很奇怪并且需要重启的地方(或者你发现,一些代码在变化) - 另一个地方就是你可以改变一个Model类。
http://www.playframework.com/documentation/1.2.5/asynchronous#SuspendingHTTPrequests
为了更容易处理我们引入的异步代码 延续。 Continuations允许您的代码被暂停 恢复透明。因此,您必须编写代码 方式,如:
public static void computeSomething(){ 承诺delayedResult = veryLongComputation(...); String result = await(delayedResult); 渲染(结果); }
实际上,您的代码将分两步执行,分为2个不同的hread。但正如你所看到的那样,它是非常的 透明的应用程序代码。
使用await(...)和continuation,你可以写一个循环:
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的播放Job类 - 所以它返回对象。有关工作的更多信息,请参阅http://www.playframework.com/documentation/1.2.5/jobs。
致电job.now()
会返回未来/承诺,您可以这样使用:await(job.now())