You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过单次AJAX调用接收PHP端多个json_encode返回数据

单次AJAX接收PHP循环逐次输出JSON响应的实现方案

默认逻辑下浏览器会等待服务端脚本完全执行完成、返回完整响应后才触发AJAX的成功回调,要实现单次请求实时接收分段输出的内容,需要同时调整PHP端的输出缓冲配置、前端AJAX的流进度监听逻辑,无需发起多次请求。

PHP端(insert.php)调整

核心是关闭所有层级的输出缓冲,每次输出后强制将内容推送到客户端,避免内容被攒到请求结束后统一返回。
调整后的完整代码:

<?php
// 关闭所有已存在的输出缓冲层级
while (ob_get_level()) {
    ob_end_clean();
}
// 设置响应头,关闭服务端缓冲、禁用缓存
header('Content-Type: text/plain; charset=utf-8');
header('X-Accel-Buffering: no'); // 关闭Nginx反向代理缓冲
header('Cache-Control: no-cache');
// 立即输出响应头
ob_flush();
flush();

$num1 = $_POST['num1'];
$num2 = $_POST['num2'];
$post_data = $_POST;
$id = [];

for ($i = 1; $i <= 10; $i++) {
    $id['id'] = $i;
    $data = array_merge($id, $post_data);
    // 输出JSON后追加换行符,作为前端分段解析的分隔标记
    echo json_encode($data) . PHP_EOL;
    // 强制将当前缓冲区内容推送到客户端
    ob_flush();
    flush();
    sleep(1);
}

注意事项:

  • 不要在脚本中主动调用ob_start()开启输出缓冲,否则会导致刷出失效
  • 如果使用Apache服务,可额外添加响应头header('Transfer-Encoding: chunked');确保分块传输生效
  • 必须关闭对应接口路径的gzip/brotli等输出压缩,压缩模块会攒够固定体量的内容才会输出,导致实时推送失效

前端AJAX逻辑调整

jQuery封装的$.ajax默认不会暴露分段响应的处理接口,需要通过原生XMLHttpRequest的onprogress事件监听流传输进度,手动解析每一段接收到的完整JSON。注意不要配置dataType: 'json',因为整个响应是多段JSON拼接的文本流,不是单个合法JSON对象。
调整后的完整前端代码:

$(function() {
  $("form").submit(function(e) {
    e.preventDefault();
    // 记录已处理的响应文本位置,避免重复解析
    let lastProcessPos = 0;

    $.ajax({
      url: "insert.php",
      method: "POST",
      data: $("form").serializeArray(),
      // 自定义原生XHR对象,绑定进度监听
      xhr: function() {
        const xhr = new XMLHttpRequest();
        xhr.onprogress = function() {
          // 截取本次新增的响应文本片段
          const newResponse = xhr.responseText.substring(lastProcessPos);
          // 按换行拆分每段JSON,过滤空内容
          const jsonChunks = newResponse.split('\n').filter(chunk => chunk.trim() !== '');
          let processedLen = 0;
          // 逐段解析JSON并渲染
          jsonChunks.forEach(chunk => {
            try {
              const data = JSON.parse(chunk);
              const txt = 'Min: ' + data.num1 + ' | Max: ' + data.num2 + ' | Numeration: ' + data.id;
              $('p').prepend(txt + '<br>');
              processedLen += chunk.length + 1; // +1 是分隔的换行符长度
            } catch (err) {
              // 遇到半截JSON(TCP分包导致)时停止处理,留到下次进度事件拼接完整后再解析
              return false;
            }
          });
          // 更新已处理位置
          lastProcessPos += processedLen;
        };
        return xhr;
      },
      beforeSend: function() {
        $('.loader').show();
      },
      complete: function() {
        // 所有内容传输完成后隐藏加载态
        $('.loader').hide();
      }
    });
  });
});

逻辑说明

  • 前端onprogress事件会在服务端每推送一段数据到客户端时触发,无需等待请求完全结束
  • 用换行符作为每段JSON的分隔标记,配合已处理位置标记,不会重复解析已经渲染过的内容
  • 增加了JSON解析容错逻辑,如果遇到TCP分包切出的半截JSON,会留到下一次进度事件和后续内容拼接完整后再解析,避免脚本报错

内容的提问来源于stack exchange,提问作者frozenade

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 23:48:51