如何用jQuery Ajax实现内容实时逐段加载(每秒新增)效果?
哦,我明白你的问题了——你的PHP脚本是每秒输出一段内容,但用普通的jQuery Ajax调用时,会等所有内容都生成完才一次性显示出来,对吧?这是因为默认的$.ajax的success回调要等到服务器完整返回响应才会触发,没法实时接收逐步输出的内容。
下面我给你两种可行的解决方案,你可以根据自己的需求选择:
方案一:利用XMLHttpRequest的onprogress事件(支持POST请求)
首先,你的PHP脚本需要确保能实时输出并刷新内容,不然服务器会把所有内容攒到一起再发送。调整你的content.php:
<?php // 关闭输出缓冲,确保内容能实时发送 ob_end_flush(); // 禁用压缩,避免内容被缓冲 ini_set('zlib.output_compression', 0); // 设置响应头,告诉客户端这是流式文本 header('Content-Type: text/plain; charset=utf-8'); header('Transfer-Encoding: chunked'); // 模拟每秒输出一段内容 for ($i = 0; $i < 5; $i++) { echo "第" . ($i + 1) . "段新增内容<br>"; // 用<br>方便页面换行 flush(); // 立刻把当前输出发送给客户端 sleep(1); // 等待1秒 } ?>
然后调整你的jQuery代码,我们需要手动创建XMLHttpRequest对象,监听它的progress事件——这个事件会在服务器有新内容返回时触发,而不是等全部完成:
<div class="div"></div> <script src="//code.jquery.com/jquery.js"></script> <script> $(document).ready(function(){ // 初始化XHR对象 const xhr = new XMLHttpRequest(); xhr.open('POST', 'content.php', true); // 设置POST请求的内容类型 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 监听进度事件:每次有新内容到达时执行 xhr.addEventListener('progress', function(e) { if (e.lengthComputable) { // 拿到当前已经显示的内容长度,提取出新增的部分 const currentContentLen = $('.div').html().length; const newContent = this.responseText.substring(currentContentLen); // 追加新增内容,而不是替换整个div $('.div').append(newContent); } }); // 监听请求完成的事件 xhr.onload = function() { console.log('所有内容加载完毕'); }; // 发送POST数据 xhr.send('name=name'); }); </script>
如果你更习惯用jQuery的$.ajax语法,也可以通过xhr选项自定义XHR对象:
<div class="div"></div> <script src="//code.jquery.com/jquery.js"></script> <script> $(document).ready(function(){ $.ajax({ url: 'content.php', type: 'post', data: { name: 'name' }, // 自定义XHR对象,添加progress监听 xhr: function() { const xhr = new XMLHttpRequest(); xhr.addEventListener('progress', function(e) { if (e.lengthComputable) { const currentLen = $('.div').html().length; const newContent = this.responseText.substring(currentLen); $('.div').append(newContent); } }); return xhr; }, success: function() { console.log('请求完成'); } }); }); </script>
方案二:使用Server-Sent Events(SSE,更适合实时推送场景)
如果你的请求可以用GET方式,SSE是更优雅的选择——它是HTML5原生支持的服务器推送技术,专门用来处理这种持续的实时内容推送。
先调整content.php为SSE格式:
<?php // SSE必须设置的响应头 header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); // 禁止缓存 header('Connection: keep-alive'); // 保持长连接 ob_end_flush(); flush(); // 模拟每秒推送一条消息 for ($i = 0; $i < 5; $i++) { // SSE的消息格式:data: 内容\n\n echo "data: 第" . ($i + 1) . "段新增内容<br>\n\n"; flush(); sleep(1); } // 推送结束信号,让客户端关闭连接 echo "data: __END__\n\n"; flush(); ?>
然后客户端代码就非常简洁了:
<div class="div"></div> <script> $(document).ready(function(){ // 创建EventSource,传入PHP脚本地址和GET参数 const source = new EventSource('content.php?name=name'); // 监听服务器发送的消息 source.onmessage = function(e) { if (e.data === '__END__') { source.close(); // 收到结束信号,关闭连接 return; } $('.div').append(e.data); }; // 监听错误(比如连接断开) source.onerror = function() { console.log('连接关闭或出错'); source.close(); }; }); </script>
关键注意点:
- PHP端的输出缓冲:一定要关闭输出缓冲并调用
flush(),否则服务器会把内容缓存起来,直到脚本执行完才一起发送。 - 客户端追加内容:不要用
html()替换整个div,要用append()来新增内容,不然每次都会覆盖之前的内容。 - SSE的限制:SSE只能用GET请求,如果必须用POST,还是选方案一的XHR方式更合适。
内容的提问来源于stack exchange,提问作者URB
相关产品推荐
相关产品推荐

