I'm trying to implement an HTML5 app that will work on desktop, android, and iOS. The app's main function is to wirelessly send commands to the server about what scripts to run and to receive regular messages pushed from that server about the status of those scripts.
The server is running nodejs and I decided to use Server Sent Events to do the push notifications. This requires that I use Firefox on Android since the native Android browser doesn't support SSE.
My implementation all works fine: the node server is publishing the events as it should and my client-side HTML5/javascript is picking it up fine on desktop chrome/firefox/safari, on my iPod iOS6, and my Android 2.2 phone.
However, there are 4 common situations that I need to handle:
Chrome/Safari behave perfectly on both desktop and iPod, as follows: if the server crashes, the site automatically reconnects and gets the pushed messages as soon as the server is up again, and if the browser app goes into the background for whatever reason, it is still getting those messages while in the background, or at the very least automatically reconnects as soon as it comes back into the foreground.
Firefox, however, both on desktop and on Android, is all too eager to close down that EventSource connection permanently. As soon as the browser loses connection to the server, either from server crash, from putting the firefox app into the background or from locking the screen, the EventSource connection is killed and does not ever try to reconnect. Of course, you can just reload the page when you come back to it, but this is annoying, especially in the case where you need to lock the screen because you need to put the phone in your pocket (this app needs to be used in some trekking situations).
Can anyone recommend any solution for this aside from just having to reload the page in Android Firefox all the time? Below is my dummy implementation, just sending random numbers every 5 seconds.
Server at /main/src
src : function(req, res) {
req.socket.setTimeout(Infinity);
// send headers for event-stream connection
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
res.write('\n');
var messageCount = 0;
var process;
function printEvent() {
messageCount++;
rand = Math.floor((Math.random()*10000)+1);
res.write('id: ' + messageCount + '\n');
res.write("data: " + rand + '\n\n');
process = setTimeout(printEvent, 5000);
}
printEvent();
res.socket.on('close', function () {
res.end();
clearTimeout(process);
});
}
Client
var source = new EventSource('/main/src');
source.onopen = function(e){
$("#test").html("Connected to server. Waiting for data...");
}
source.onmessage = function(e){
$("#test").html("MSG: " + e.data);
}
source.onerror = function(e){
var txt;
switch(e.target.readyState){
case EventSource.CONNECTING:
txt = 'Reconnecting...';
break;
case EventSource.CLOSED:
txt = 'Connection failed. Will not retry.';
break;
}
$("#test").html("Error: " + txt);
}
Thanks!!
i know only one solution, that is already used in many libs: "heartbeat" messages - on the client side you may check, if the "random number" is not received from the server in 10 seconds (5000 seconds + some lag) - the connection is seems to be broken and you should do the reconnection (with native EventSource you may use "close" method, than create new EventSource OR you can try https://github.com/Yaffle/EventSource )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With