Как отправить данные json_encode с помощью HTML5 SSE

У меня есть сценарий, который запускает событие SSE для получения данных, закодированных в формате json, из online.php. При поиске в Google я нашел способы отправки данных JSON с помощью sse, введя переносы строк.

То, что я ищу, это как отправить JSON через SSE, когда массив JSON создается с помощью функции PHP json_encode().

Я написал следующие строки кода, но кто-нибудь может мне помочь, где добавить "данные: \n\n", необходимые для SSE?

<script>
if(typeof(EventSource)!=="undefined")
{
  var source=new EventSource("online.php");
  source.onmessage=function(event)
  {
     var data=JSON.parse(event.data);
     $("#new_message").html("Inbox"+data['total']);
  };    
}
else
{
  $("#new_message").html("HTML5 not supported");
}
</script>

online.php

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$data["total"]="hello";
echo json_encode($data);
ob_flush();
flush(); 
?>

3 ответа

Решение

Вам нужно отправить его в формате EventStream, который в этом случае просто добавляет его к data:

echo 'data: ' . json_encode($data) . "\n\n";

Вы можете кодировать $data Массив, как сказал Райан:

echo 'data: ' . json_encode($data) . "\n\n";

Затем на стороне клиента, event.data будет рассматриваться как строка, которую затем можно легко проанализировать в json с помощью запроса jQuery.parseJSON(), поэтому ваш клиентский код будет выглядеть примерно так:

// Check if the browser supports SSE
if (typeof (EventSource) !== "undefined") {

              var source = new EventSource("script.php");
              // Handle evetns
              source.onmessage = function(event) {
                  // parse the data that has an object as a string
                  var msg = $.parseJSON(event.data);
                     // Do awesome code with the values inside msg
              };
        } else {
              alert("Sorry, your browser doesn't support this awesome feature!");
        }

Источник: http://api.jquery.com/jquery.parsejson/

Ваш скрипт будет показывать вывод только один раз, так как для продолжения его работы необходим какой-то цикл (конечно, условно, иначе у вас будут запущены миллионы экземпляров!!).

Я выделил реализацию, которую я написал ранее сегодня, которая демонстрирует это, а также добавил несколько дополнительных javascript/jquery, чтобы помочь лучше управлять потоками. Ниже также будет работать с однопоточной установкой PHP, такой как Xampp (для локальной разработки). Примечания по Xampp: Поскольку скрипт PHP находится в цикле и не завершается немедленно, он остановит запуск нового скрипта php или agax. Если вы также используете ajax для вызова PHP, вызовите stream_close() в beforesend и stream_open() в обратных вызовах success.

Приведенное ниже не проверено, но в основном оно извлекается из рабочего кода, поэтому все должно быть в порядке.

<?
//stream.php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

stream();

function stream(){
    $data = array();
    //collect data from database or wherever to stream to browser
    //example data
        $data[0]["name"] = 'Bob';
        $data[0]["total"] = rand(0,100);
        $data[0]["name"] = 'Jane';
        $data[0]["total"] = rand(0,100);

    //maybe there is no new data so just send one new line
    //this is required to check if the connection is still alive
    if(!empty($data)){  
        echo "\n";
    }else{              //Otherwise json encode the data for output
        echo 'data: '.json_encode($data)."\n\n";
    }
    flush();            //Flush the result to the browser
    sleep(1);           //Wait a second (or what ever you like)

    //If the browser is still connected
    if(!connection_aborted() && connection_status()==0){
        stream();       //recurse the function
    }
}

?>

<script>
    var webstream = false;

    function stream_open(){
        stream_close(); //Close the stream it (in case we got here weirdly)
        if(!!window.EventSource){   //Test compatibility
            webstream = new EventSource('./stream.php');
            console.log("Stream Opened");   //Log event for testing

            webstream.addEventListener('message', function(e){
                var data = JSON.parse(e.data);  //Parse the json into an object
                process_stream(data);
            },false);

            //Cleanup after navigating away (optional)              
            $(window).bind('beforeunload', function(){  
                webstream.onclose = function(){}; //delete onclose (optional)
                webstream.close();  //Close the stream
            });
        }
    }

    function stream_close(){
        if(typeof(webstream)=="object"){
            webstream.close();
            webstream = false;
            console.log("Stream Closed");   //Log event for testing
        }
    }

    function process_stream(data){
        //do something with the new data from the stream, e.g. log in console
        console.log(data);
    }


    //Optional:
    //Toggle stream on blur/focus
    //Good if the user opens multiple windows or Xampp?
        $(window).on("blur focus", function(e) {

            //get the last blur/focus event type
            var prevType = $(this).data("prevType") || null;

            if (prevType != e.type){
                console.log(e.type);    //Log event for testing (focus/blur)
                switch (e.type){
                    case "blur":
                        stream_close(); //Close stream on blur
                    break;
                    case "focus":
                        stream_open();  //Open stream on focus
                    break;
                }
            }

            //Store the last event type to data
            $(this).data("prevType", e.type);
        });

    // Optional:
    // Using idletimer plugin to close the stream in times of inactivity
    // https://github.com/thorst/jquery-idletimer/blob/master/src/idle-timer.js

        $(document).on("idle.idleTimer", function (){
            stream_close();
        });
        $(document).on("active.idleTimer", function (){
            stream_open();
        });
        $(document).idleTimer({timeout:5000}); //5 second idle timer
</script>
Другие вопросы по тегам