如何在等待AJAX请求结果时实时获取PHP分段输出内容?
实现AJAX实时获取PHP分段输出
核心原理
默认情况下PHP会缓冲输出内容,直到脚本执行完毕才一次性发送给客户端;普通jQuery AJAX只会在请求完成后接收全部响应。要实现实时获取,需要关闭PHP输出缓冲,同时前端使用原生XMLHttpRequest监听onprogress事件来实时接收分段内容。
1. 修改PHP代码(关键:强制实时输出)
关闭PHP的输出缓冲机制,确保每段内容生成后立即发送给客户端:
// 开启自动刷新,关闭输出缓冲 ob_implicit_flush(1); // 清空已存在的缓冲内容,避免积压 ob_end_clean(); // 输出第一段内容并强制发送 echo 'abc'; flush(); sleep(5); // 输出第二段内容并强制发送 echo 'def'; flush(); sleep(5); // 输出最后一段内容并强制发送 echo 'ghi'; flush();
2. 修改前端代码(用原生XHR监听实时输出)
jQuery的$.ajax不支持监听实时进度事件,必须使用原生XMLHttpRequest来处理:
// 初始化加载弹窗 Swal.fire({ title: 'Please wait..', html: 'We are checking. <br/>This process may take some time.', allowOutsideClick: false, didOpen: () => { Swal.showLoading() } }); // 创建XHR对象 const xhr = new XMLHttpRequest(); xhr.open('POST', VIP_AJAX_URL + '/add'); // 设置请求头,适配表单格式 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 记录已处理的字符长度,避免重复解析内容 let receivedLength = 0; // 监听进度事件,实时获取新输出 xhr.onprogress = function(e) { if (e.lengthComputable) { // 提取本次新增的内容 const newContent = e.responseText.substring(receivedLength); if (newContent) { console.log('实时收到:', newContent); // 这里可以根据需求更新UI,比如修改弹窗内容 // Swal.update({ html: '已收到:' + newContent }); // 更新已处理长度 receivedLength = e.responseText.length; } } }; // 请求完成后的处理 xhr.onload = function() { Swal.close(); const response = xhr.responseText.trim(); if (response === 'success') { console.log('处理完成'); } else { Swal.fire({ icon: 'error', title: 'Oops...', html: response, }); } }; // 请求出错处理 xhr.onerror = function() { Swal.close(); Swal.fire({ icon: 'error', title: '请求出错', text: '网络请求发生错误,请重试', }); }; // 发送请求,注意参数编码避免乱码 xhr.send('slug=' + encodeURIComponent(slug));
注意事项
- 如果使用Nginx服务器,可能需要在配置中关闭FastCGI缓冲:
fastcgi_buffering off;,否则服务器会将PHP输出攒到一起发送,导致实时效果失效。 - 前端必须对请求参数做
encodeURIComponent编码,避免特殊字符导致参数解析错误。
内容的提问来源于stack exchange,提问作者emrez
相关产品推荐
相关产品推荐

