Developing a web application that uses server-sent events is quite easy. You'll need a bit of code on the server to stream the events to the web application, but the web application side of things works almost identically to handling any other type of event.
The server-sent event API is contained in the EventSource
interface; to open a connection to the server to begin receiving events from it, create a new EventSource
object specifying the URI of a script that generates the events. For example:
var evtSource = new EventSource("ssedemo.php");
If the event generator script is hosted on a different domain a new EventSource object should be created that specifies both the URI and options dictionary. For example, assuming the client script is on example.com:
var evtSource = new EventSource("//api.example.com/ssedemo.php", { withCredentials: true } );
Note: using EventSourceis not supported by all browsers. Please check out the Browser compatibility section.
Once you've instantiated your event source, you can begin listening for messages:
evtSource.onmessage = function(e) { var newElement = document.createElement("li"); newElement.innerHTML = "message: " + e.data; eventList.appendChild(newElement); }
This code listens for incoming messages (that is, notices from the server that do not have an event
field on them) and appends the message text to a list in the document's HTML.
You can also listen for events, using addEventListener()
:
evtSource.addEventListener("ping", function(e) { var newElement = document.createElement("li"); var obj = JSON.parse(e.data); newElement.innerHTML = "ping at " + obj.time; eventList.appendChild(newElement); }, false);
This code is similar, except that it will be called automatically whenever the server sends a message with the event
field set to "ping"; it then parses the JSON in the data
field and outputs that information.
The server-side script that sends events needs to respond using the MIME type text/event-stream. Each notification is sent as a block of text terminated by a pair of newlines. For details on the format of the event stream, see Event stream format.
The PHP code for the example we're using here follows:
date_default_timezone_set("America/New_York"); header('Cache-Control: no-cache'); header("Content-Type: text/event-stream\n\n"); $counter = rand(1, 10); while (1) { // Every second, send a "ping" event. echo "event: ping\n"; $curDate = date(DATE_ISO8601); echo 'data: {"time": "' . $curDate . '"}'; echo "\n\n"; // Send a simple message at random intervals. $counter--; if (!$counter) { echo 'data: This is a message at time ' . $curDate . "\n\n"; $counter = rand(1, 10); } ob_end_flush(); flush(); sleep(1); }
The code above generates an event every second, with the event type "ping". Each event's data is a JSON object containing the ISO 8601 timestamp corresponding to the time at which the event was generated. At random intervals, a simple message (with no event type) is sent.
Note: You can find a full example that uses the code shown in this article on GitHub — see Simple SSE demo using PHP.
When problems occur (such as a network timeout or issues pertaining to access control), an error event is generated. You can take action on this programmatically by implementing the onerror
callback on the EventSource object:
evtSource.onerror = function(e) { console.log("EventSource failed."); };
As of Firefox 22, it does not appear that there is any way to distinguish between different kinds of error events.
By default, if the connection between the client and server closes, the connection is reset. The connection is terminated with the .close()
method.
evtSource.close();
The event stream is a simple stream of text data which must be encoded using UTF-8. Messages in the event stream are separated by a pair of newline characters. A colon as the first character of a line is in essence a comment, and is ignored.
Each message consists of one or more lines of text listing the fields for that message. Each field is represented by the field name, followed by a colon, followed by the text data for that field's value.
The following field names are defined by the specification:
event
addEventListener()
to listen for named events. The onmessage
handler is called if no event name is specified for a message.data
data:
, it will concatenate them, inserting a newline character between each one. Trailing newlines are removed.id
EventSource
object's last event ID value.retry
All other field names are ignored.
In the following example, there are three messages sent. The first is just a comment, since it starts with a colon character. As mentioned previously, this can be useful as a keep-alive if messages may not be sent regularly.
The second message contains a data field with the value "some text". The third message contains a data field with the value "another message\nwith two lines". Note the newline special character in the value.
: this is a test stream data: some text data: another message data: with two lines
This example sends some named events. Each has an event name specified by the event
field, and a data
field whose value is an appropriate JSON string with the data needed for the client to act on the event. The data
field could, of course, have any string data; it doesn't have to be JSON.
event: userconnect data: {"username": "bobby", "time": "02:33:48"} event: usermessage data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."} event: userdisconnect data: {"username": "bobby", "time": "02:34:23"} event: usermessage data: {"username": "sean", "time": "02:34:36", "text": "Bye, bobby."}
You don't have to use just unnamed messages or typed events; you can mix them together in a single event stream.
event: userconnect data: {"username": "bobby", "time": "02:33:48"} data: Here's a system message of some kind that will get used data: to accomplish some task. event: usermessage data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}
Feature | Chrome | Edge | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
EventSource support | 6 | No support | 6.0 (6.0) | No support | (Yes) | 5 |
Available in shared and dedicated workers[1] | (Yes) | No support | 53.0 (53.0) | No support | (Yes) | (Yes) |
Feature | Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|
EventSource support | 4.4 | 45 | No support | 12 | 4.1 |
Available in shared and dedicated workers[1] | (Yes) | 53.0 (53.0) | No support | (Yes) | (Yes) |
[1] But not service workers as yet.
© 2005–2018 Mozilla Developer Network and individual contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events