【发布时间】:2011-06-03 18:42:04
【问题描述】:
我正在编写一些 PHP,它会进行大量处理,然后生成结果报告。以前它会定期执行 flush(),但我们正在迁移到 Zend Framework 并且不能再这样做了。相反,我希望在生成报告时更新某种状态显示。所以我做了一个进度条,在 iframe 中加载,将共享内存添加到进度条更新操作和报告生成操作,并通过 xmlhttprequest 加载输出。这一切都很好。我的问题是浏览器想要串行而不是并行执行这两个请求,因此它将请求进度条,然后阻塞,直到进度条完成,然后再请求实际输出。这意味着这个过程永远不会结束,因为真正的工作永远不会开始。
我整个上午都在寻找解决这个问题的方法,结果空手而归。 有什么方法可以导致两个连接,还是我只是搞砸了?
我的下一个动作是将处理进一步分解,让状态更新动作完成实际工作,保存结果,然后使用其他动作转储它。这会很痛苦,我想避免它。
编辑:这是 javascript,根据要求:
function startProgress()
{
var iFrame = document.createElement('iframe');
document.getElementsByTagName('body')[0].appendChild(iFrame);
iFrame.id = 'progressframe';
iFrame.src = '/report/progress';
}
function Zend_ProgressBar_Update(data)
{
document.getElementById('pg-percent').style.width = data.percent + '%';
document.getElementById('pg-text-1').innerHTML = data.text;
document.getElementById('pg-text-2').innerHTML = data.text;
}
function Zend_ProgressBar_Finish()
{
document.getElementById('pg-percent').style.width = '100%';
document.getElementById('pg-text-1').innerHTML = 'Report Completed';
document.getElementById('pg-text-2').innerHTML = 'Report Completed';
document.getElementById('progressbar').style.display = 'none'; // Hide it
}
function ajaxTimeout(){
xmlhttp.abort();
alert('Request timed out');
}
var xmlhttp;
var xmlhttpTimeout;
function loadResults(){
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{
// code for IE6, IE5
xmlhttp=new ActiveXObject(\"Microsoft.XMLHTTP\");
}
xmlhttp.open(\"POST\",\"/report/output\",true);
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
clearTimeout(xmlhttpTimeout);
document.getElementById('report-output').innerHTML=xmlhttp.responseText;
}
}
var xmlhttpTimeout=setTimeout(ajaxTimeout,600000); // Ten minutes
xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xmlhttp.send('".file_get_contents("php://input")."');
}
这从以下 onload 脚本中调用:
onload="startProgress(); setTimeout(loadResults,1000);"
问题不在于 Javascript。如果你在其中放置一个 alert(),警报将在正确的时间触发,但浏览器会延迟第二个 http 事务,直到第一个完成。
感谢大家的意见。
在我们的开发计划允许的时间范围内,我没有为此提出令人满意的答案。似乎每个常见的浏览器都希望在与该站点进行多项交易时重新使用与该站点的现有连接。我想不出的任何东西都不会导致浏览器按需启动并行连接。每当有来自同一服务器的两个请求时,客户端都希望以串行方式执行它们。
我最终将处理分成几部分并将其移动到状态栏更新操作中,将报告输出保存到服务器上的临时文件中,然后使状态栏完成函数启动 xmlhttprequest 以加载结果。输出操作只是吐出临时文件的内容,然后将其删除。
【问题讨论】:
-
你能发布你正在使用的javascript吗?
-
你为什么使用 iframe 来显示进度条。为什么不直接用 XMLHttpRequest 来实现呢?这些函数是如何被调用的?
-
我试图使它成为一个 xmlhttprequest,但是浏览器没有解释返回的 javascript。我将它恢复为 iframe,因为它起作用了。我可以稍后尝试使其与 xmlhttprequest 一起使用,假设这甚至可行。这些函数是通过页面 body 标记的 onload 调用的。
-
为什么要返回 JavaScript? :/ 我看不出 iFrame 无法加载的原因。
-
iframe 确实加载了。问题是 xmlhttprequest 在 iframe 完全加载之前被阻止。由于 iframe 是 xmlhttprequest 内容生成的进度指示,因此它永远不会完成。 iframe 中的 javascript 是移动进度指示器的命令。请参阅 Zend_ProgressBar 的手册以了解该机制的说明。
标签: php javascript zend-framework