>情况:
我正在使用 $.ajax(( POST 向一个 php 脚本发送请求,该脚本将大约 400,000-500,000 行插入到数据库中。 这始终需要大约 3.5 - 4 分钟。(在此期间,请求处于挂起状态(。
问题:
我需要一些方法来在页面上显示进度。(如 %(。 我尝试在每 5 秒左右检查一次的 setInterval 中使用 $.ajax((,但它们似乎在第一个(更长的($.ajax(( 完成后累积并全部通过。
问题:
$.ajax(( 不是默认异步的吗? 这难道不应该意味着请求可以以任何顺序和任何时间发送出去,并且应该以任何顺序和任何时间收到响应吗?这甚至与异步有什么关系吗?有没有办法从一个请求定期发回"半响应"?或者,当有挂起的请求/响应时,我无法发送和接收请求/响应? (见下面的真棒图(
提前谢谢!!
http://kshaneb.com/reqres.png 多个请求
长时间运行的 ajax-call 可能会在服务器上打开一个会话,因此由于会话文件锁定,所有下一个请求都会被阻止。
问题: 默认情况下,PHP 将其会话数据写入文件。当向启动会话 (session_start(( 的 PHP 脚本发出请求时,此会话文件将被锁定。这意味着,如果您的网页向PHP脚本发出大量请求,例如,通过Ajax加载内容,则每个请求都可能锁定会话并阻止其他请求完成。 其他请求将挂起 session_start((,直到会话文件解锁。如果您的某个 Ajax 请求运行时间相对较长,则尤其糟糕。
溶液: 会话文件将保持锁定状态,直到脚本完成或手动关闭会话。要防止多个 PHP 请求(需要 $_SESSION 数据(阻塞,您可以启动会话,然后关闭会话。这将解锁会话文件并允许其余请求继续运行,甚至在初始请求完成之前。
更多信息在这里:http://konrness.com/php5/how-to-prevent-blocking-php-requests/
希望这有帮助
$(function ()
{
var statusElement = $("#status");
// this function will run each 1000 ms until stopped with clearInterval()
var i = setInterval(function ()
{
$.ajax(
{
success: function (json)
{
// progress from 1-100
statusElement.text(json.progress + "%");
// when the worker process is done (reached 100%), stop execution
if (json.progress == 100) clearInterval(i);
},
error: function ()
{
// on error, stop execution
clearInterval(i);
}
});
}, 1000);
});
与其做 ajax 帖子,不如发布到 iframe 并让 php 生成增量输出并使用 flush 命令发送。
// send a hash mark for every 1000 inserts
$a = 0;
while ($rec = getDataForNextInsert()){
$a++;
// do insert
if ($a%1000 == 0) { echo '#'; flush(); }
}
然后,还可以轮询iframe的内容,为最终用户提供漂亮的显示。
我希望这对你有用
首先,您需要在PHP脚本中禁用输出缓冲区
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
ob_implicit_flush(1);
然后,您需要在此过程中从 PHP 回显您的进度,如下所示:
for($i=0;$i < 20;$i++){
echo ($i > 0 ? "#":"").($i/20*100);
sleep(1);
}
然后,在javascript中,您需要侦听xhr readystate更改事件,当发生这种情况时,只需解析响应文本并根据需要显示进度即可。
侦听事件:
$.ajaxPrefilter(function( options, _, jqXHR ) {
if ( options.onreadystatechange ) {
var xhrFactory = options.xhr;
options.xhr = function() {
var xhr = xhrFactory.apply( this, arguments );
function handler() {
options.onreadystatechange( xhr, jqXHR );
}
if ( xhr.addEventListener ) {
xhr.addEventListener( "readystatechange", handler, false );
} else {
setTimeout( function() {
var internal = xhr.onreadystatechange;
if ( internal ) {
xhr.onreadystatechange = function() {
handler();
internal.apply( this, arguments );
};
}
}, 0 );
}
return xhr;
};
}
});
和 ajax 请求的示例:
$.ajax({
url: "test.php",
cache: false,
onreadystatechange: function( xhr ) {
res = xhr.responseText.split("#");
$("#id").html(res[res.length-1] + "% done<br/>");
}
}).done(function( data ) {
$("#id").append("all done!</br>");
});
});
使用 jQuery 1.5+ 进行测试