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

WordPress中jQuery AJAX调用PHP时逐次返回响应实现进度条的方案

实现PHP运行过程中逐次向前端返回响应的方案

核心原理说明

你需要的技术是服务器发送事件(Server-Sent Events,SSE),基于HTTP分块传输编码实现,单请求连接建立后,服务端可以多次向客户端推送数据,无需发起多次AJAX请求,完美适配进度条实时更新的需求。
普通jQuery AJAX的success/done回调仅会在HTTP请求完全结束后触发,本身不支持中途接收阶段性响应,因此无需在原生AJAX能力上做尝试。你之前调用wp_send_json_success()只能拿到一次返回的原因是,该函数底层会调用wp_die()直接终止PHP程序执行,且普通HTTP请求仅允许返回一次完整响应,自然无法获取后续进度。

代码实现

WordPress后端(PHP)修改

需要调整原有AJAX接口的响应头和输出逻辑,关闭输出缓冲,按照SSE协议格式输出数据:

<?php
class Test {
    public function __construct() {
        add_action('wp_ajax_nopriv_test', [$this, 'ajax_test'], 20);
        add_action('wp_ajax_test', [$this, 'ajax_test'], 20);
    }
    public function ajax_test() {
        // 关闭压缩和缓冲,避免输出被合并
        if (function_exists('apache_setenv')) {
            apache_setenv('no-gzip', '1');
        }
        @ini_set('zlib.output_compression', 0);
        @ini_set('implicit_flush', 1);
        // 清空所有已有的输出缓冲
        while (ob_get_level()) {
            ob_end_clean();
        }
        // 设置SSE协议必填响应头
        header('Content-Type: text/event-stream');
        header('Cache-Control: no-cache');
        header('Connection: keep-alive');
        $args = [
            'post_type'         => 'product',
            'post_status'       => 'publish',
            'posts_per_page'    => -1,
            'order'             => 'ASC',
            'orderby'           => 'ID',
        ];
        $products = new WP_Query($args);
        $total_count = $products->found_posts;
        $current_index = 0;
        if($products->have_posts()) :
            while($products->have_posts()): $products->the_post();
                global $post;
                $current_index++;
                // 按照SSE格式输出数据:每行以data:开头,末尾加两个换行符
                echo "data: " . json_encode([
                    'progress' => round(($current_index / $total_count) * 100, 2),
                    'post_id' => $post->ID,
                    'status' => 'running'
                ]) . "\n\n";
                // 强制冲刷缓冲区,将数据立刻发送到前端
                flush();
            endwhile;
            // 推送任务完成标记
            echo "data: " . json_encode([
                'status' => 'complete',
                'total_processed' => $current_index
            ]) . "\n\n";
            flush();
        endif;
        exit;
    }
}
new Test();

前端代码修改

无需使用jQuery AJAX,直接用原生EventSource接口接收SSE推送即可:

// 拼接请求地址,参数规则和原有admin-ajax请求一致
const sseRequestUrl = new URL(admin_ajax_url);
sseRequestUrl.searchParams.set('action', 'test');
// 建立SSE长连接
const eventSource = new EventSource(sseRequestUrl);
// 监听服务端推送的消息
eventSource.onmessage = function (event) {
    const res = JSON.parse(event.data);
    console.log('收到推送数据:', res);
    // 此处更新进度条UI
    if (res.progress) {
        // 示例:更新进度条宽度
        // $('.progress-bar').css('width', res.progress + '%');
    }
    // 任务完成后关闭连接
    if (res.status === 'complete') {
        eventSource.close();
        console.log('所有任务处理完成');
    }
};
// 异常处理
eventSource.onerror = function (err) {
    console.error('连接出错:', err);
    eventSource.close();
};

注意事项

  • 若使用Nginx作为Web服务器,需要关闭对应请求路径的代理缓冲,否则输出会被Nginx缓存后统一返回,无法实时推送,在Nginx配置中添加:proxy_buffering off;
  • 不要使用wp_send_json、wp_send_json_success这类WordPress提供的JSON返回函数,这类函数执行后会主动终止PHP程序,无法继续执行后续任务
  • SSE默认仅支持GET请求,若需要传递大量敏感参数,可使用SSE POST polyfill实现POST请求的SSE能力

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 01:54:03