heyblackduck
heyblackduck

Reputation: 117

How to flush PHP output buffer properly?

I need PHP to stream output to Javascript but Javascript keeps the old responses and prints them like so...

Console logs:

[0]: Line to show.
[0]: Line to show.[1]: Line to show. 
[0]: Line to show.[1]: Line to show.[2]: Line to show.
[0]: Line to show.[1]: Line to show.[2]: Line to show.[3]: Line to show.
[0]: Line to show.[1]: Line to show.[2]: Line to show.[3]: Line to show.[4]: Line to show.

[0]: Line to show.[1]: Line to show.[2]: Line to show.[3]: Line to show.[4]: Line to show.Array
(
    [0] => [0]: Line to show.
    [1] => 
    [2] => 
    [3] => [1]: Line to show.
    [4] => 
    [5] => 
    [6] => [2]: Line to show.
    [7] => 
    [8] => 
    [9] => [3]: Line to show.
    [10] => 
    [11] => 
    [12] => [4]: Line to show.
    [13] => 
    [14] => 
)

So Javascript console logs state that the responseText is "saving" old responses. However, take a look at the array I saved in PHP and you can see that no previous echos are flushed to JS.

Javascript:

                $.ajax({
                    url: "../controller/controller.php", 
                    type: "POST",
                    data: {operation: 'rxMode'},
                    xhr: function(){
                        var xhr = $.ajaxSettings.xhr();
                        xhr.onprogress = function(e){ console.log(e.currentTarget.responseText); };
                        console.log(xhr);
                        return xhr;
                    }
                 });

PHP:

        $out = array();
        for ($i = 0; $i<5; $i++){
            echo "[$i]: Line to show.";
            array_push($out, ob_get_contents());
            ob_flush();
            array_push($out, ob_get_contents());
            flush();
            array_push($out, ob_get_contents());
            sleep(2);
        }
        print_r($out);

My desired responseText is

[0]: Line to show.
[1]: Line to show.
[2]: Line to show.
[3]: Line to show.
[4]: Line to show.

Edit: I do not want to remove the old responses rather I would prefer that Javascript only gives me my desired responseText.

Upvotes: 1

Views: 1990

Answers (1)

Barmar
Barmar

Reputation: 780724

responseText always contains the entire response from the server. When you use the progress event, it contains the accumulated response so far, not just the incremental string added to the response in the most recent flush from the server.

Save the length of the previous response text in a variable, and then on subsequent calls just print the substring after that.

var responseLen = 0;
$.ajax({
    url: "../controller/controller.php", 
    type: "POST",
    data: {operation: 'rxMode'},
    xhr: function(){
        var xhr = $.ajaxSettings.xhr();
        xhr.onprogress = function(e){
            console.log(e.currentTarget.responseText.substr(responseLen)); 
            responseLen = e.currentTarget.responseText.length;
        };
        console.log(xhr);
        return xhr;
    }
 });

Upvotes: 4

Related Questions