考虑写入div的AJAX调用:
recent_req=$.post('result.php', { d: data }, function(returnData) {
$('#content').html(returnData);
});
result.php
处的PHP脚本执行一些需要花费时间的功能,每步约5-20秒。我正在使用PHP的flush()
函数在每个步骤开始和结束时立即将信息提供给浏览器,但是如何让Javascript将数据写入#content
div中?
感谢。
修改
澄清:假设result.php
如下所示,由于约束不能实际重构:
<?php
echo "Starting...<br />";
flush();
longOperation();
echo "Done with first long operation.<br />";
flush();
anotherLongOperation();
echo "Done with another long operation.<br />";
flush();
?>
如何构建AJAX以调用result.php
,以便在它们进入时将echo语句附加到#content
div?有/无jQuery的任何解决方案都是受欢迎的。谢谢!
答案 0 :(得分:5)
有一种技术可以使用iframe来实现这一目标。
与涉及框架的其他建议类似,但它不涉及会话或轮询或任何其他内容,并且不需要您显示iframe本身。它还具有在流程中的任何一点运行您想要的任何代码的好处,以防您使用UI进行更复杂的操作,而不仅仅是将文本推送到div(例如,您可以更新进度条)。
基本上,将表单提交给隐藏的iFrame,然后将javascript刷新到该帧,该帧与iFrame父级中的函数进行交互。
像这样:
<强> HTML:强>
<form target="results" action="result.php" method="post">
<!-- your form -->
<input type="submit" value="Go" />
</form>
<iframe name="results" id="results" width="0" height="0" />
<div id="progress"></div>
Javascript,在您的主页中:
function updateProgress(progress) {
$("#progress").append("<div>" + progress + "</div>");
}
<强> result.php:强>
<?php
echo "<script language='javascript'>parent.updateProgress('Starting...');</script>";
flush();
longOperation();
echo "<script language='javascript'>parent.updateProgress('Done with first long operation.');</script>";
flush();
anotherLongOperation();
echo "<script language='javascript'>parent.updateProgress('Done with another long operation.');</script>";
flush();
?>
答案 1 :(得分:4)
您无法使用常规的ajax调用“流式传输”数据,因为您无法让用户的浏览器“监听”服务器请求。只有在数据处理完毕后才会调用“成功”功能。
但是,有很多关于互联网上'Ajax Push'的讨论,显然HTML5上有websocket对象,可用于让用户的浏览器监听服务器请求。语法定义还不是很稳定,所以你不想搞砸它,因为它可能很快就会改变。您可能要做的是发送step1请求,等待其返回,然后发送step2请求。它会为你的整体处理时间增加一些开销(并且会使它更加冗长),但如果你只有几个重要的步骤它应该可以正常工作。如果您的步骤不需要太多处理,则不应该这样做(因为通信时间将大于您的“有效处理时间”)。
编辑:您还可以做的是例如在用户会话中写入进度。这样,您可以定期ping服务器并请求更新状态。这样,即使您有许多小步骤,您也只需每10秒左右发送一次请求,这是对每一步的调度的改进。
答案 2 :(得分:3)
作为替代解决方案,您可以向form
提交隐藏的iframe
,如以下示例所示:
<?php
function output_data($data) {
echo str_pad($data, 4096, ' ', STR_PAD_RIGHT) . "\n";
flush();
}
function long_runner() {
output_data("");
output_data(date("H:i:s").' - Starting...<br />');
sleep(10);
output_data(date("H:i:s").' - Done with first long operation.<br />');
sleep(10);
output_data(date("H:i:s").' - Done with another long operation.<br />');
return("<script>parent.task_complete()</script>");
}
if (isset($_REQUEST["status"])) {
die(long_runner());
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Write to IFRAME as data streams in</title>
<style>
#myform { display: none }
#frm { width: 50% }
</style>
<script language="javascript" type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
function task_complete() {
alert('Task completed');
}
$(document).ready(function() {
$('#starter').click(function() {
$('#myform').submit();
});
});
</script>
</head>
<body>
<form id="myform" method="get" target="frm" action="<?= $_SERVER['SCRIPT_NAME'] ?>">
<input type="hidden" name="status" value="0">
</form>
<a href="#" id="starter">Start</a><br />
<iframe id="frm" name="frm" frameborder="0"></iframe>
</body>
</html>
答案 3 :(得分:3)
将动态数据流写入div:
这里......你具体询问如何动态地将数据流写入“div”。正如许多人所说,可以动态地写入iframe,我们只需要更进一步。以下是您的问题的完整解决方案,它将把数据带回您的div,最大延迟为.5秒。如果您需要更快速的更新,可以对其进行调整。
<!DOCTYPE html>
<html>
<head>
<title>dynamic listener</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
var count;
$(function(){
$('#formx').submit(function(){
setTimeout(function(){ check_div(); }, 500);
count = 0;
return true;
});
});
function check_div()
{
var $iframetxt = $('#iframex').contents().text();
var $div = $('#dynamic');
if( $iframetxt != $div.text() )
{
console.log('rewritten!');
$div.text( $iframetxt );
setTimeout(function(){ check_div(); }, 500);
count = 0;
}
else
{
count++;
if(count < 40) setTimeout(function(){ check_div(); }, 500);
else console.log('timed out');
}
}
</script>
</head>
<body>
<div>
Form
<form id="formx" action="result.php" method="post" target="iframex">
<input type="submit" />
</form>
</div>
<div id="dynamic"></div>
<iframe id='iframex' name="iframex" style="display:none" ></iframe>
</body>
</html>
<强> 1。在表单提交时,流数据将发送到iframe。
为此,我们只需将表单标记中的target属性设置为iframe名称。
<强> 2。 check_div()每隔0.5秒运行一次,以将#dynamic div的文本与iframe的文本内容进行比较。
如果它们之间存在差异,则会将数据写入div并再次调用超时。如果没有差异,则超时计数器递增。如果计数小于40(40 x .5秒= 20秒),则再次调用超时。如果没有,我们假设流已经完成。
答案 4 :(得分:2)
以下是使用会话进行轮询的解决方案:
<!DOCTYPE html>
<html>
<body>
<div id="content"></div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
var pollTimeout;
function pollResult(){
$.get('poll.php', function(response) {
// Update #content with partial response
$('#content').html(response);
pollTimeout = setTimeout(pollResult, 1000);
});
}
$.post('result.php', function(response) {
// Result is loaded, stop polling and update content with final response
clearTimeout(pollTimeout);
$('#content').html(response);
});
// Start polling
pollResult();
</script>
</body>
</html>
<?php
class SemiStream{
public function __construct(){
@session_start();
$_SESSION['semi_stream'] = '';
}
public function write($data){
@session_start();
$_SESSION['semi_stream'] .= $data;
// We have to save and close the session to be
// able to read the contents of it in poll.php
session_write_close();
}
public function close(){
echo $_SESSION['semi_stream'];
unset($_SESSION['semi_stream']);
}
}
$stream = new SemiStream();
$stream->write("Starting...<br />");
sleep(3);
$stream->write("Done with first long operation.<br />");
sleep(3);
$stream->write("Done with another long operation.<br />");
$stream->close();
echo 'Done.';
<?php
session_start();
echo $_SESSION['semi_stream'];
这没有使用PHP的输出缓冲。
答案 5 :(得分:0)
查看推送服务,看起来它可以完全符合您的要求:http://pusher.com/
答案 6 :(得分:0)
问题可能是如何在您的应用中实施Push技术。我建议你看 this question which has great answer with example