Home >Web Front-end >JS Tutorial >Server-sent Events
Core points
Content-type
header (value text/event-stream
) and UTF-8 character encoding. The syntax for the server to send events includes data, event type, event identifier, and retry interval. onmessage
function (only for applications that send message events), but the addEventListener
method is more flexible for handling custom events. Suppose your country's national basketball team is participating in the World Basketball Championship. You want to follow the game, but you can't watch it because the game time conflicts with your working hours.
Luckily, your National News Service has a very outstanding web development team. They built a sports information scrolling display that updates whenever a foul or score occurs. When you visit a URL, the update will be pushed directly to your browser. Of course, you'll want to know how they did it. The answer is: the server sends the event.
Server Send Events is a way to use a stream to push data and/or DOM events from the server to the client. It is suitable for stock quotes, sports scores, flight tracking, email notifications – any situation where data needs to be updated regularly.
Wait!
I heard you say, Can't we already do this using XMLHttpRequest or WebSockets?
Yes, yes. However, doing so requires extending these objects to implement the functionality of EventSource itself.
Since the server sends events are data streams, they require long-term connections. You need to use a server that can handle a large number of simultaneous connections. Of course, event-driven servers are particularly suitable for streaming events. These include Node.js, Juggernaut, and Twisted. For Nginx, you can use the nginx-push-stream-module module. However, server configuration is outside the scope of this article and will vary depending on the server you are using.
Let's see how to subscribe to a stream using EventSource object. Then we will see how events are sent and processed.
Creating an EventSource object is simple.
<code class="language-javascript">var evtsrc = new EventSource('./url_of/event_stream/',{withCredentials:false});</code>
The EventSource constructor accepts up to two parameters:
withCredentials
attribute. Dictionaries are syntactically similar to objects, but they are actually associative arrays of data with defined name-value pairs. In this case, withCredentials
is the only possible dictionary member. Its value can be true or false. (For more information about dictionaries, see the Web IDL specification.)
Dictionary parameters are required only if cross-domain requests for user credentials (cookies). So far, no browser supports cross-domain EventSource requests. Therefore, we will not include the second parameter in the example.
When the EventSource connection is open, it will trigger a open
event. We can define a function that handles the event by setting the onopen
property.
<code class="language-javascript">var evtsrc = new EventSource('./url_of/event_stream/'); evtsrc.onopen = function(openevent){ // 连接打开时执行的操作 }</code>
If there is a problem with our connection, an error will be triggered. We can use the onerror
property to define a handler function for these events. We will discuss the causes of some error events in the "Training Errors" section.
<code class="language-javascript">evtsrc.onerror = function(openevent){ // 发生错误时执行的操作 }</code>
Story events default to message events. To handle message events, we can use the onmessage
attribute to define a handler function.
<code class="language-javascript">evtsrc.onmessage = function(openevent){ // 接收到消息事件时执行的操作 }</code>
We can also use addEventListener()
to listen for events. This is the only way to handle custom events, as we will see in the Processing Events section.
<code class="language-javascript">var onerrorhandler = function(openevent){ // 执行的操作 } evtsrc.addEventListener('error',onerrorhandler,false);</code>
To close the connection, use the close()
method.
<code class="language-javascript">evtsrc.close();</code>
Therefore, we created the EventSource object and defined the handler for the opening, message, and error events. However, in order for this method to work, we need a URL for streaming events.
The server sends the event is a snippet of text delivered as part of the stream from the URL. In order for the browser to treat our data as a stream, we must:
Content-type
header (value is text/event-stream
) to provide content; The syntax for the server to send events is simple. It consists of one or more colon-separated field name-value pairs followed by a newline character. The field name can contain one of four possible values.
data:
: The message to be sent. event:
: The type of event being dispatched. id:
: The event identifier to be used when the client reconnects. retry:
: How many milliseconds should pass before the browser tries to reconnect to the URL. Among them, only the data
field is required.
In this example, we will send an event to announce which teams are playing in our tournament matches. When the browser receives this text, it dispatches a message event.
<code class="language-javascript">var evtsrc = new EventSource('./url_of/event_stream/',{withCredentials:false});</code>The value of the
data
field will become the value of the data
attribute of the message event. As mentioned above, the server sends an event by default is a message event. But as we will discuss later, we can also dispatch custom events by including the event
field.
We can also send several pieces of data as a single event. Each piece of data should be followed by a newline character (line newline, carriage return, or both). Here we are appending an event that includes this game location and attendance.
<code class="language-javascript">var evtsrc = new EventSource('./url_of/event_stream/'); evtsrc.onopen = function(openevent){ // 连接打开时执行的操作 }</code>
For this event, the value of the data
attribute will be: Air Canada CentrenToronto, Ontario, CanadaAttendance: 19,800.
Please note the blank lines between events. In order for the client to receive an event, the event must be followed by a blank line. Comments begin with a colon.
Unless we specify otherwise, the type of event is a message. To do this, we need to include a event
field. In the following example, we will add two startingfive
events to our stream and send our data as a string in JSON format.
<code class="language-javascript">evtsrc.onerror = function(openevent){ // 发生错误时执行的操作 }</code>
Here, we need to listen to startingfive
events instead of message events. However, our data
field will still become the value of the data
property of the event.
We will discuss the data
properties and the MessageEvent interface in the "Processing Events" section.
Now, although the server does push events to the browser, the reality is more subtle. If the server keeps the connection open, the EventSource request will be an extended request. If it is closed, the browser will wait a few seconds before reconnecting. For example, if the URL sends an end-of-file tag, the connection may be closed.
Each browser has its own default reconnect interval. Most will reconnect after 3 to 6 seconds. However, you can control this interval by including the retry
field. The retry
field indicates how many milliseconds the client should wait before reconnecting to the URL. Let's build and change our event from the example above to include a 5 second (5000 milliseconds) retry interval.
<code class="language-javascript">evtsrc.onmessage = function(openevent){ // 接收到消息事件时执行的操作 }</code>
Event streams can be kept active as long as the client is connected. Depending on your architecture and application, you may want the server to close the connection periodically.
When the browser reconnects to the URL, it will receive any data available at the connection point. However, for the game information scrolling display, we may want to let the visitor know what he or she has missed. This is why the best practice for setting id to each event. In the following example, we are sending id as part of the scoring event.
<code class="language-javascript">var evtsrc = new EventSource('./url_of/event_stream/',{withCredentials:false});</code>
The value should be unique to the stream. In this case, we are using the time of the shot score.
Theid
field becomes the lastEventId
property of this event object. But it has another purpose. If the connection is closed, the browser will include a Last-Event-ID
header in its next request. Think of it as a bookmark for the stream. If the Last-Event-ID
header exists, you can adjust the application's response so that only events that follow it are sent.
As mentioned above, all events default to message events. Each message event has three properties, defined by the MessageEvent interface.
onmessage
function will be called. This works great for applications that you only send message events. However, if you want to send a score or startingfive
event (as shown in our example), its limitations become obvious. More flexible using addEventListener
. In the following code, we are using addEventListener
to handle the startingfive
event.
<code class="language-javascript">var evtsrc = new EventSource('./url_of/event_stream/'); evtsrc.onopen = function(openevent){ // 连接打开时执行的操作 }</code>
(Second part, due to space limitations, please ask questions in paragraphs.)
The above is the detailed content of Server-sent Events. For more information, please follow other related articles on the PHP Chinese website!