Reputation: 11
I am trying to update a specific element in my HTML document using server-sent events. I am using the W3Schools example with parameters changed to fit my needs. When this did not work out of the box, I tried this question's solution, which is to include charset=utf-8
in my Content-Type header. Still no updates to the HTML. I then realized I was getting the following error:
EventSource's response has a MIME type ("text/html") that is not "text/event-stream". Aborting the connection.
Here is the relevant JavaScript in my .js file:
var source = new EventSource("warehouse.php");
source.onmessage = function(event) {
document.getElementById("processing").innerHTML += event.data + "<br>";
};
In my PHP file, I have the following:
if (isset($args->products)) {
orderProducts($args->products);
}
function orderProducts($products) {
$bigResponse = outgoingData(constant('bigURL'), $products[0]);
$littleResponse = outgoingData(constant('lilURL'), $products[3]);
header('Content-Type: text/event-stream; charset=utf-8');
header('Cache-Control: no-cache');
echo "data: Order has been placed.";
flush();
}
I am completely stumped. What am I missing? How do I fix this error?
Upvotes: 1
Views: 3788
Reputation: 1103
Try sending a json encoded data part/element back to the browser.
Lets see if I can remember correctly... It's out of my mind, so it isn't tested!
PHP Side:
// Set SSE headers which are send along first output.
header('Content-Type: text/event-stream; charset=UTF-8');
header('Cache-Control: no-cache');
$sseId = 0; //Increment this value on each next message
$event = 'eventName'; //Name of the event which triggers same named event-handler in js.
//$data needs to be json encoded. It can be a value of any type.
$data = array ('status' => 'Progress', 'message' => 'My message or html');
//Send SSE Message to browser
echo 'id: ' . $sseId++ . PHP_EOL; //Id of message
if (!is_null($event)) {
echo 'event: ' . $event . PHP_EOL; //Event Name to trigger eventhandler
}
retry: 10000 . PHP_EOL; //Define custom reconnection time. (Default to 3s when not specified)
echo 'data: ' . json_encode($data) . PHP_EOL; //Data to send to eventhandler
//Note: When sending html, you might need to encode with flags: JSON_HEX_QUOT | JSON_HEX_TAG
echo PHP_EOL;
ob_flush();
flush();
JavaScript side:
var es = new EventSource('sse.php');
es.addEventListener('eventName', function(event) {
var returnData = JSON.parse(event.data);
var myElement = document.getElementById("processing");
switch (returnData.status) {
case 'Error':
es.close();
myElement.innerHTML = 'An error occured!';
break;
case 'Done':
es.close();
myElement.innerHTML = 'Finished!';
break;
case 'Progress':
myElement.innerHTML += returnData.message + "<br>";
break;
}
});
es.onerror = function() {
console.log("EventSource failed.");
};
In this case I make use of 1 (named) event only where the data element contains a status on which js reacts.
You can also define multiple event-names to be used as a status and define corresponding event-handlers or define a handler which is triggered on each message received.
es.onmessage = function(event) {
//This handler fires on each message received.
console.log("Incoming message.");
};
If you have server-side script running longer then 3s, specify a longer retry time in the message sent (See code at PHP side). Otherwise the browser will reconnect after 3 seconds which might run your script from the beginning and abandon the previous run.
Upvotes: 2