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

Vue实现Laravel应用中textarea无缓冲实时更新的问题

解决Vue实时展示PHP流式输出的问题

你的核心问题在于axios默认会等待整个HTTP响应完成后才触发回调,没法处理PHP端的增量输出。要实现实时更新,我们需要换用支持流式响应监听的请求方式,同时确保PHP端的输出配置完全正确。下面是分步解决方案:

一、修改Vue的请求逻辑:用XMLHttpRequest替代axios

XMLHttpRequest提供了onprogress事件,可以在数据逐步返回时实时捕获内容。修改你的onCommand方法:

onCommand: function onCommand(task, websiteid) {
    const _this3 = this;
    const xhr = new XMLHttpRequest();
    xhr.open('POST', '/' + task + '/' + websiteid, true);
    
    // 必须设置Laravel需要的CSRF Token
    const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
    xhr.setRequestHeader('X-CSRF-TOKEN', csrfToken);
    xhr.setRequestHeader('Content-Type', 'application/json');

    // 实时监听数据返回
    xhr.onprogress = function() {
        // responseText会累积所有已接收的内容,计算新增部分避免重复添加
        const newContent = xhr.responseText.substring(_this3.comment_body.length);
        if (newContent) {
            _this3.comment_body += newContent;
        }
    };

    // 请求完成后的收尾处理
    xhr.onload = function() {
        if (xhr.status === 200) {
            _this3.comment_body += '\n|------ ' + task + ' 执行完成 ----|';
        } else {
            try {
                const errorData = JSON.parse(xhr.responseText);
                _this3.errors.record(errorData.errors);
            } catch (e) {
                _this3.errors.record({ general: '请求执行失败' });
            }
        }
    };

    xhr.onerror = function() {
        _this3.errors.record({ general: '网络请求出错' });
    };

    // 发送请求数据(和之前axios的payload一致)
    xhr.send(JSON.stringify(this.$data));
}

同时别忘了给textarea加上Vue的双向绑定,否则数据更新不会同步到视图:

<textarea v-model="comment_body" name="comment_body" id="update-comment" placeholder="output goes here, feel free to notate" rows="10" class="update-comment"></textarea>

二、修复PHP端的输出配置

确保PHP的输出完全无缓冲,并且禁用服务器的压缩(压缩会强制缓冲内容):

public function yourCommandHandler(Request $request) {
    // 禁用缓存与压缩,这一步是关键!
    header('Cache-Control: no-cache, no-store, must-revalidate');
    header('Pragma: no-cache');
    header('Expires: 0');
    header('Content-Type: text/plain; charset=utf-8');
    
    // 禁用Apache的gzip压缩(如果服务器开启了的话)
    if (function_exists('apache_setenv')) {
        apache_setenv('no-gzip', 1);
    }
    ini_set('zlib.output_compression', 0);
    
    // 清空所有已存在的输出缓冲
    ob_end_clean();

    var_dump( "something1");
    ob_flush(); flush(); // 立即发送内容
    
    echo "$command";
    ob_flush(); flush();
    
    $this->process_wrapper($command);
    
    echo "something4";
    ob_flush(); flush();
}

public function process_wrapper($cmd, $data = null) {
    $descr = array(
        0 => array( 'pipe', 'r' ) ,
        1 => array( 'pipe', 'w' ) ,
        2 => array( 'pipe', 'w' )
    );
    $pipes = array();
    
    echo "something2";
    ob_flush(); flush();
    
    echo "something3";
    ob_flush(); flush();
    
    $process = proc_open($cmd, $descr, $pipes, realpath('./'), array());
    if (is_resource($process)) {
        while ($f = fgets($pipes[1])) {
            echo $f;
            ob_flush(); flush();
            // 加个微小延迟,避免浏览器合并小输出块(可选但推荐)
            usleep(10000); // 10毫秒
        }
        proc_close($process);
    }
}

三、关键注意事项

  1. 服务器层面的缓冲:如果用Nginx,需要在对应location配置中添加proxy_buffering off;,否则Nginx会缓冲响应内容再发给浏览器。
  2. 浏览器缓冲:部分浏览器会累积一定量的内容才更新视图,输出换行符或者少量空白字符可以触发即时更新。
  3. CSRF Token:Laravel的POST请求必须携带CSRF Token,别忘了在页面头部添加<meta name="csrf-token" content="{{ csrf_token() }}">。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:18:28