Introduction to Server-Sent Events
While the web development world is abuzz over the “exciting future” of Web Sockets, there’s another spec along the same lines that has me far more excited: Server-Sent Events. This spec is based on a feature that was first called Server-Sent DOM Events and implemented in Opera 9. The idea is pretty simple: a web page can subscribe to a stream of events generated by the server. Whenever an event occurs on the server, a notification is sent to the client and a JavaScript event is generated.
Differences from Web Socket
The biggest difference between Web Sockets and Server-Sent Events is that the former is bidirectional while the latter is not. Server-Sent Events, as the name implies, are sent from the server to the browser only. If you wish to send data to the server, you’ll have to do so through another mechanism, such as XMLHttpRequest.
The second fairly large difference is that Server-Sent Events are sent over plain old HTTP without any modification. This is good news for implementers as there won’t be changes on the server aside from ensuring that high-duration requests don’t crash your server. Using HTTP ensures that Server-Sent Events won’t be hampered in its progress by the same protocol angst that is still swirling around Web Sockets.
The API
The JavaScript API for Server-Sent Events is very similar to that of Web Sockets. To subscribe to a new event stream, you start by creating a new EventSource object and pass in the entrypoint:
var source = new EventSource("myevents.php");
Note that the referenced URL must be on the same origin (scheme, domain, and port) as the page in which the object is created. The EventSource instance has a readyState property that is set to 0 to indicate it’s connecting to the server, 1 to indicate an open connection, and 2 to indicate a closed connection.
There are also three events: open, which is fired when the connection is established, message, which is fired when a new event is received from the server, and error, which is fired when no connection can be made. In general usage, the onmessage event handler is likely the one you’ll use the most:
source.onmessage = function(event){
var data = event.data;
};
Information sent back from the server is returned via event.data as a string.
By default, the EventSource object will attempt to keep the connection alive with the server. You can force the object to disconnect immediately and stop attempting to reconnect by calling the close() method:
source.close();
The event stream
The server events are sent along a long-lasting HTTP request with a MIME type of text/event-stream. The format of the response is plain text and, in its simplest form, is made up of the prefix data: followed by text, such as:
data: foo
data: bar
data: foo
data: bar
The first part of this stream fires a message event with event.data set to “foo”; the second part fires a message event with event.data set to “bar”; the third fires a message event with event.data set to “foo\nbar” (note the newline character in between). When there are two or more consecutive lines beginning with data:, it is interpreted as a multiline piece of data and the values are concatenated together with a newline character. The message event is never fired until a blank line is encountered after a line containing data:, so be certain to include that extra newline when generating the event stream on the server.
You can also associate an ID with a particular event by including an id: line before or after the data: line(s):
data: foo
id: 1
By setting an ID, the EventSource object keeps track of the last event fired. If the connection is dropped, a special HTTP header called Last-Event-ID is sent along with the request so that the server can determine which event is appropriate to fire next.
Wrap up
Server-Sent events are a simpler alternative to Web Sockets for server push technology. Although some people seem convinced that bidirectional communication is an absolute necessity, many of the proposed use cases for Web Sockets are actually implementable using Server-Sent Events. This includes streaming stock quotes, score updates for games, bidding updates for auctions, etc. Opera 10.7 has an implementation of Server-Sent Events, and an implementation has already made it into the WebKit repository as well. Before jumping on the Web Sockets bandwagon, consider if Server-Sent Events can accomplish the same task.
Update (2010-Oct-22): Fixed typo.
Disclaimer: Any viewpoints and opinions expressed in this article are those of Nicholas C. Zakas and do not, in any way, reflect those of my employer, my colleagues, Wrox Publishing, O'Reilly Publishing, or anyone else. I speak only for myself, not for them.
Both comments and pings are currently closed.




9 Comments
When generating the response, is there any recommendation on how long a single data-line should/can be? So when using json_encode(), can one just send the long string or would some kind of splitting be required?
Keep up your fantastic work!
– Christoph
Christoph on October 19th, 2010 at 11:13 am
Thanks, Nicholas, but, what is your opinion: Is it already time to even start researching capabilities provided by functionality like this? In recent years there were plenty of new enticing standards sometimes even backed by real implementations. But any average new project contains IE7+ item among the list of supported browsers. And Opera and WebKit never were at the beginning of the list (if at all present).
Consequently, when I see another interesting topic like Server-Sent events, I usually make a note somewhere deep in my mind and leave it alone. The bag of these notes swells rapidly but it is still of no tangible use.
We still must care of “those damn IE6 users,†as it was brilliantly explained in your last post.
So, what do you think?
Alexei on October 19th, 2010 at 11:14 am
Hey Nick,
Interesting post – glad to see someone with a vast readership is getting the word out about the EventSource API. As it turns out I’ve been researching and developing for the EventSource API for
several months now and have even published a jQuery utility plugin for managing Event Sources in your jQuery applications – complete with support fallbacks for browsers that do not yet have Event Source implemented. Additionally, I also hosted a break out session at this past weekend’s jQuery Conference Boston to raise awareness of the EventSource API and had a pretty good attendance.
Here are the links to my work:
http://github.com/rwldrn/jquery.eventsource
http://gist.github.com/553303
http://weblog.bocoup.com/javascript-eventsource-support-updated-in-opera-10-70
http://weblog.bocoup.com/chrome-6-server-sent-events-with-new-eventsource
http://weblog.bocoup.com/jquery-eventsource-yakyakface-com
http://weblog.bocoup.com/javascript-creating-an-eventsource-within-a-worker ( http://gist.github.com/552549 )
Rick Waldron on October 19th, 2010 at 11:52 am
That’s a cool technology. It sounds like it’d be easier to implement than websockets, but I guess well have to see where the browsers and supportive technologies go.
This reminded me of the asp.net developers I’ve worked with who seemed to think click events triggered on the server. It was such a common mistake to the point where I’m sure .Net has been harming the mental model of it’s developers.
Jethro Larson on October 19th, 2010 at 2:01 pm
Nicholas,
I had been waiting for a decent synopsis on server-side events and so it was really great to find this article.
Like you I believe that for many push applications a bidirectional channel is not required. I also imagine that simplifying the communication between client and server could yield some interesting scaling benefits.
As this is a young technology which doesn’t enjoy full browser support yet, I see this as an opportunity for projects such as CometD 2 and node.js to support and perhaps more importantly create the fallback mechanism for browsers that are not quite up to snuff yet.
Mark
Mark Boas on October 19th, 2010 at 4:44 pm
Hi Nicholas,
I’ve been following your questions to WHATWG. There are still a few things I don’t get about the spec.
If the line contains no semicolons, then the whole line is interpreted as a field name, with no field. Fields “event”, “id” and “retry” with no value makes no sense to me (well, altough an empty-string event type is allowed according to the DOM3 Events spec and browsers’ initEvent implementations).
I think “line without semicolons become a filed name” part is just nonsense and no one would use it, so should be ommited. What do think?
Now, a line with only “data” (or “data:”) is tricky. The spec has an example of that. When you get one of such line, you don’t fire an event. When you have two of such lines, you do fire an event with event.data = ‘\n’. However, when I asked Anne on WHATWG list, he thinks the first case should fire an event with empty string data. (So the example is wrong?)
http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2010-October/028813.html
edvakf on October 19th, 2010 at 5:25 pm
@edvakf – I believe the spec is still full of vague wording and incorrect examples. Sending data: with no following value really shouldn’t fire an event. I intend to keep dissecting the spec to figure out the ins and outs.
Nicholas C. Zakas on October 19th, 2010 at 7:29 pm
Very nice, well explained article as usual. I did not even know something like this existed. Thanks.
A minor type “creash your server”
Amit Behere on October 19th, 2010 at 7:53 pm
Very Informative !! So much to learn from your articles!!
One question on my mind. How are server sent events different from what we call Comet (also called reverse AJAX), wherein server holds on to a HTTP request initiated by browser (through XHR). There after, server keeps flushing the data when requried.?
Keyur Nayak on October 26th, 2010 at 4:43 am
Comments are automatically closed after 14 days.