HTML5 EventSource for all events?

I have push notifications in my JavaScript client application using EventSource. I can attach event listeners as follows:

source.addEventListener('my_custom_event_type', function(e) { console.log(e.data); }, false); 

But I want to track all events that are pushed from the server (mainly for debugging), so if some event is sent, but it does not have an event listener, I can easily find it. I mean, I don’t just want to “ignore” all events that are not tied to events.

I would expect to do something like this:

 source.addEventListener('*', function(e) { console.debug('Event with no listener attached: ', e); }, false); 

But specs and training aids like those of html5rocks do not indicate whether this is possible or not.

On the other hand, it could be some firefox / chrome extension, which allows you to track all server events or something like that. These things will really help in the development of push notifications.

Thanks!

+13
javascript html5 server-sent-events
source share
4 answers

I myself figure out a solution that also greatly improves the EventSource interface.

Server side . Do not send event type, just add an extra data field (so that I always use json). Therefore, instead of

 event: eventName data: {mykey: 'myvalue'} 

I am sending this from the server:

 data: {mykey: 'myvalue', eventName: 'eventName'} 

Client side . Now I can use the EventSource onmessage event callback, which is fired for every message that does not have an event type.

And for communication event listeners, I create a wrapper class with Backbone.Event functionality. Result:

 // Server Sent Events (Event Source wrapper class) var MyEventSource = (function() { function MyEventSource(url) { var self = this; _.extend(this, Backbone.Events); this.source = new EventSource(url); this.source.onmessage = function(event) { var data, eventName; var data = JSON.parse(event.data); var eventName = data.eventName; delete data.eventName; // Now we can monitor all server sent events console.log('app.server.on ', eventName, '. Data: ', data); self.trigger(eventName, data); }; } return MyEventSource; })(); 

Now with this wrapper class I can easily extend the functionality, all events sent by the server can be easily tracked and thanks to the Backbone.Events extension, event handling in this class is much more powerful.

Usage example:

 var source = new MyEventSource('url/of/source'); // Add event listener source.on('eventName', function(data) { console.log(data); }); // Fire a event (also very useful for testing and debugging!!) source.trigger('eventName', { mykey: 'myvalue' }); // Unbind event listener (very important for complex applications) source.off('eventName'); 

Now I have a component that is easy to process, extend, debug, and test.

+27
source share
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"></script> <script> var content = ''; if(typeof(EventSource)!=="undefined") { var source = new EventSource("demo_sse.php"); source.onmessage = function(event) { content+=event.data + "<br>"; $("#result").html(content); }; } else { $("#result").html("Sorry, your browser does not support server-sent events..."); } </script> 
0
source share

I know that this is not an EventSource, but I was looking for the same thing (a way to catch all incoming events without knowing their type). Without any control over the server sending these events, I ended up just writing it using XHR if anyone else comes across this:

 function eventStream(path, callback){ //Create XHR object var xhr = new XMLHttpRequest(); //initialize storage for previously fetched information var fetched=''; //Set readystatechange handler xhr.onreadystatechange=function(){ //If the connection has been made and we have 200, process the data if(xhr.readyState>2 && xhr.status==200){ //save the current response text var newFetched=xhr.responseText; //this is a stream, so responseText always contains everything //from the start of the stream, we only want the latest var lastFetch=xhr.responseText.replace(fetched, ''); //Set the complete response text to be removed next time var fetched=newFetched; //callback to allow parsing of the fetched data callback(lastFetch); } }; //open and send to begin the stream; xhr.open('GET', path, true); xhr.send(); } parseEvents=function(response){ var events=[]; //split out by line break var lines=response.split("\n"); //loop through the lines for(var i=0;i<lines.length;i++){ //each event consists of 2 lines, one begins with //"name:", the other with "data" //if we hit data, process it and the previous line if(lines[i].substr(0, lines[i].indexOf(':'))=='data'){ //add this event to our list for return events.push({ //get the event name name: lines[i-1].split(':')[1].trim(), //parse the event data data: $.parseJSON(lines[i].substr(lines[i].indexOf(':')+1).trim()) }); } } //return the parsed events return events; }; evenStream('http://example.com/myEventPath', function(response){ var events=parseEvents(response); }); 
0
source share

tothemario from tothemario above for the hint I needed to figure this out.

It looks like you MAY send events back to the browser with a custom type, but in order to trigger the MESSAGE event, you must assign a listener to the new type, not the message type.

If you look at the client-side code below, we hope to illustrate this.

For context, my server dispatches an event with a custom type of CustomType . So I subscribe to an event listener of this type and add another listener for message as an interception of everything else.

In this CustomType process, the CustomType event that enters the browser from the CustomType another listener.

  <script type="text/javascript"> var CustomTypeList = []; function EventSystemOpen(e) { console.log("EventSystemOpen", e); } function EventSystemError(e) { console.log("EventSystemOpen", e); if (e.readyState == EventSource.CLOSED) { // } } function GotServerEventMessage(e) { console.log("GotServerEventMessage", e); } function GotCustomType(e) { CustomTypeList.push(JSON.parse(e.data)); console.log("Added CustomType", e, JSON.parse(e.data), CustomTypeList); } if (!!window.EventSource) { var source = new EventSource('api/listen'); source.addEventListener('open', EventSystemOpen, false); source.addEventListener('error', EventSystemError, false); source.addEventListener('message', GotServerEventMessage, false); source.addEventListener('CustomType', GotCustomType, false); } </script> 
0
source share

All Articles