Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Server-sent events: How do you automatically reconnect in a cross-browser way?

I implement some code to query the database for any changes and to send an event. Here's the code of my PHP script

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

//****Some code here to query the database

echo "event: message\n";
echo "data: change_from_database \n";
echo "\n\n";
ob_flush();
flush();

I'm relying on the browser to automatically reconnect each time the connection closes, so I don't implement any loop on my server code. In addition, I learned from this thread that implementing an infinite loop has many disadvantages.

So everything works fine client-side: the browser reconnects each time the connection closes and an event is fired each time the server sends one; well except for Firefox (40.0.2) which doesn't reconnect. I know it doesn't because I wrote some JavaScript error checking code to test this:

var evtSource = new EventSource("../sse.php");
evtSource.onerror = function(event){
    var txt;
    switch( event.target.readyState ){
    case EventSource.CONNECTING:
        txt = 'Reconnecting...';
        break;
    }
    console.log(txt);
}

So after like each second, the console on chrome for example logs "Reconnecting". Firefox on the other hand reconnects once and never does so again.

How do I write code to make this work on Firefox, and perhaps other browsers which support server-sent events but don't reconnect automatically?

like image 906
Cedric Ipkiss Avatar asked Aug 18 '15 18:08

Cedric Ipkiss


Video Answer


2 Answers

With the recent version of the Firefox browser (44.0.2), your code works perfectly. However, you can reinitialize your EventSource object in the error handler like this:

var evtSource = new EventSource("../sse.php");
var evtSourceErrorHandler = function(event){
    var txt;
    switch( event.target.readyState ){
        case EventSource.CONNECTING:
            txt = 'Reconnecting...';
            break;
        case EventSource.CLOSED:
            txt = 'Reinitializing...';
            evtSource = new EventSource("../sse.php");
            evtSource.onerror = evtSourceErrorHandler;
            break;
    }
    console.log(txt);
}

But I strongly do not recommend you to do this because your code doesn't use benefits of keeping the connection alive (as you wrote, you are aware of infinite loop) so browser does simple polling (you can see this in then network tab). I don't see any reason to use SSE over AJAX without keeping a permanent connection, which is obviously hard to maintain with PHP. So I assume using simple AJAX polling in this situation.

like image 154
max Avatar answered Oct 19 '22 21:10

max


You could use a polyfill like this one https://github.com/Yaffle/EventSource which should add the event source functionality to unsupported browsers.

like image 3
user874639 Avatar answered Oct 19 '22 19:10

user874639