Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do server-sent events initiate every 3 seconds? [duplicate]

I am new to server-sent events, so I am trying this W3Schools example on WAMP Server. The files I have are:

demo_sse.php

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

  $time = date('r');
  echo "data: The server time is: {$time}\n\n";
  flush();
?>

index.php

<!DOCTYPE html>
<html>
  <body>
    <h1>Getting server updates</h1>
    <div id="result"></div>
    <script>
      if(typeof(EventSource) !== "undefined") {
        var source = new EventSource("demo_sse.php");
        source.onmessage = function(event) {
          document.getElementById("result").innerHTML += event.data + "<br>";
        };
      } else {
        document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
      }
    </script>
  </body>
</html>

As far as I understand, time is constantly changing, so the updates must be sent every second (at least). However, the updates are received every three seconds. This interval was not specified in demo_sse.php, so:

  • Why does it send the updates every 3 seconds?
  • How do I change this interval?
like image 319
Wais Kamal Avatar asked Dec 21 '18 16:12

Wais Kamal


People also ask

How does server-sent events work?

So what are Server-Sent Events? A client subscribes to a “stream” from a server and the server will send messages (“event-stream”) to the client until the server or the client closes the stream. It is up to the server to decide when and what to send the client, for instance, as soon as data changes.

Why are servers sent events?

They are commonly used to send message updates or continuous data streams to a browser client and designed to enhance native, cross-browser streaming through a JavaScript API called EventSource, through which a client requests a particular URL in order to receive an event stream.

What is server-sent events in Java?

What are Server-Sent Events? SSE definition states that it is an http standard that allows a web application to handle a unidirectional event stream and receive updates whenever the server emits data. In simple terms, it is a mechanism for unidirectional event streaming.


2 Answers

The example on W3Schools is a bit of a bad example.

For most HTTP response/requests exchanges, the client makes an HTTP request to the server, the server sends back data and the exchange is complete.

For SSE (although it still uses the HTTP protocol) this works a bit different. Here the client makes a request to the server, the session remains open and the server can send data whenever it pleases. If the session is closed for whatever reason, the EventSource will try to reconnect and everything starts over.

The problem in your PHP script is that the script ends the request/response exchange after it finished the last line. This means that the connection is closed and so the EventSource will try to reconnect. (Adding an .onerror event will show that an error is raised after every message.)

As is defined in the specification:

A reconnection time, in milliseconds. This must initially be a user-agent-defined value, probably in the region of a few seconds.

This is why you receive updates every three seconds. Because that is what the user-agent-defined value is set to.

Just below that line you can also see:

Apart from url these are not currently exposed on the EventSource object.

This means that this value cannot currently be set from JavaScript.

It is possible though to set this value from your server by defining it in the retry field in the SSE message. Here you can define in miliseconds how long the user agent should wait before reconnecting to your server. If you want to set it to one second it should be:

$time = date('r');
// If the connection closes, retry in 1 second
echo "retry: 1000\n";
echo "data: The server time is: {$time}\n\n";
flush();

But of course it would be better to implement SSE properly without closing the connection after the first message.

A good explanation can be found on MDN. I recommend to use MDN over W3Schools in general. W3Schools is not the most liked resource here on Stack Overflow and this is a good example why.

like image 128
Ivar Avatar answered Oct 19 '22 17:10

Ivar


According to this article on the late, great HTML5 Rocks:

The magical part is that whenever the connection is closed, the browser will automatically reconnect to the source after ~3 seconds. Your server implementation can even have control over this reconnection timeout. See Controlling the reconnection-timeout in the next section.

The demo_sse.php ends after the flush, so the connection is closed; the browser is automatically reconnecting in 3(ish) seconds.

To control the reconnection timeout on the server, you can send a retry field in the stream. From this MDN doc it can be determined that if you add echo "retry: 1000\n\n"; line before the echo "data: line, it will change the timeout to 1 second.

like image 28
DinoCoderSaurus Avatar answered Oct 19 '22 19:10

DinoCoderSaurus