在我的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>
爪哇:
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()的调用非常快 - 它为实际工作分离了一个新线程。那么为什么它会被调用两次呢?我该如何阻止呢?
[更新:5/24/17]
我怀疑,作为JSF的完全新手,我没有正确使用actionListeners和remoteCommands。 @BalusC有几个回应&amp;像this和this这样的文章表明这可能是一个范围问题。
为了回答我为什么不简单地从commandButton actionListener返回文件的问题,因为生成.zip文件可能需要几分钟。因此,我通过分离工作线程来避免阻止UI,并且我还使用<p:blockUI>
元素来娱乐用户。
答案 0 :(得分:0)
如果遇到其他人,我通过将bean的javascript回调移动到oncomplete
的{{1}}属性来解决它。它现在看起来像这样:
JSF:
commandButton
爪哇:
<p:commandButton id="downloadBtn" value="Download" disabled="#{bean.selectedRow == null}"
onclick="blockUI()" oncomplete="downloadFileWhenReady()"
actionListener="#{bean.generateFile()}"/>
<p:remoteCommand name="checkForDownloadReady" actionListener="#{bean.checkForDownloadReady}"/>
<!-- Hidden button to contain the fileDownload element -->
<p:commandButton id="downloadFile" ajax="false" style="display:none" onclick="releaseUI();">
<p:fileDownload value="#{bean.file}" contentDisposition="attachment"/>
</p:commandButton>
<script type="text/javascript">
function downloadFileWhenReady() {
window.setTimeout(function () {checkForDownloadReady();}, 1000);
}
function doTheActualDownload() {
document.getElementById('the_form:downloadFile').click();
}
function blockUI() {
PF('blocker').show();
}
function releaseUI() {
PF('blocker').hide();
}
</script>