I am trying to implement an HTML5 application that will work on desktop computers, Android and iOS. The main function of the application is to wirelessly send commands to the server about which scripts to run and receive regular messages displayed from this server about the status of these scripts.
The server starts nodejs, and I decided to use Server Sent Events to send push notifications. This requires me to use Firefox on Android, since the native Android browser does not support SSE.
My implementation works fine: the node server publishes events as it should, and my client HTML5 / javascript types it on the chrome / firefox / safari desktop, on my iPod iOS6 and my Android 2.2 phone.
However, there are four situations that I need to handle:
- device loses wifi signal
- Nodejs server error (hope this is not common!)
- set the browser in the background on iPod / Android while viewing another application, etc.
- Screen lock on iPod / Android while the browser is working
Chrome / Safari behaves perfectly both on the desktop and on the iPod, as shown below: if the server crashes, the site automatically reconnects and receives the pressed messages as soon as the server logs in again, and if the browser application goes into the background for for some reason, it still receives these messages in the background, or at least automatically recovers as soon as it returns to the foreground.
Firefox, however, both on the desktop computer and on Android, too wants to close the EventSource connection forever. As soon as the browser loses connection with the server, either from a server failure, from installing the firefox application in the background, or from locking the screen, the EventSource connection is killed and never tries to connect. Of course, you can just reload the page when you return to it, but this is annoying, especially when you need to lock the screen because you need to put the phone in your pocket (this application needs to be used in some camping situations).
Can anyone recommend a solution for this other than having to constantly refresh the page in an Android browser? 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!!