【发布时间】:2017-10-23 20:43:58
【问题描述】:
在我的 PrimeFaces 应用程序中,我正在生成一个文件以供下载。一代开始了,然后我进入一个等待循环,直到它准备好。现在看来,这个循环被启动了两次。代码如下:
JSF:
<p:commandButton id="downloadBtn" value="Download" disabled="#{bean.selectedRow == null}"
onclick="blockUI()"
actionListener="#{bean.generateFileAndDownloadWhenReady()}"/>
<script type="text/javascript">
function downloadFileWhenReady(key) {
window.setTimeout(function () {
checkForDownloadReady([{name:"key",value: key }]);
}, 1000);
}
function doTheActualDownload(key) {
// handle the download
}
</script>
Java:
public void generateFileAndDownloadWhenReady() {
key = kickoffFileGeneration();
RequestContext.getCurrentInstance().execute("downloadFileWhenReady('" + key + "');");
}
public void checkForDownloadReady() {
String key = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("key");
STATUS status = FileCache.getFileStatus(key);
if (status == STATUS.READY) {
RequestContext.getCurrentInstance().execute("doTheActualDownload(" + key + ");");
} else if (status == STATUS.FAILED) {
logger.error("Failure creating file. Wail loop will end.");
} else if (status == STATUS.OPEN){
RequestContext.getCurrentInstance().execute("downloadFileWhenReady('" + key + "');");
}
}
通过在 generateFileAndDownloadWhenReady() 中放置断点,我可以看到它只被调用一次,但在 downloadFileWhenReady() 中的断点被调用了两次。通过使用长循环延迟,我知道第二个调用不是来自循环。此外,对 kickoffFileGeneration() 的调用非常快——它为实际工作启动了一个新线程。那么为什么它会被调用两次,我该如何阻止它呢?
[更新:2017 年 5 月 24 日]
我怀疑,作为 JSF 的新手,我没有正确使用 actionListeners 和 remoteCommands。 @BalusC 有几个回复和文章,例如 this 和 this,这表明这可能是一个范围界定问题。
并回答为什么我不只是简单地从 commandButton actionListener 返回文件的问题,这是因为生成 .zip 文件可能需要几分钟时间。因此,我通过分离工作线程来避免阻塞 UI,并且我还使用 <p:blockUI> 元素来娱乐用户。
【问题讨论】:
-
那么最好学习“推送”而不是实现自己的轮询机制,最好不要创建自己的线程。搜索如何在现代 Web 应用中执行异步操作
-
感谢@Kukeltje 的提示。我确实调查过它,但读到并非所有浏览器都支持“推送”,所以无论如何我都必须有一个轮询后备。我也不喜欢投票,所以下次我会记住这一点。 (此外,这是一个低流量的私人应用程序,希望能减少它的罪恶。);-)
-
定义'所有浏览器'...当前的FF、Chrome和IE都支持它。如果不是,他们会退回到长轮询,这正是您要实现的目标
标签: java jsf primefaces