Home > Web Front-end > JS Tutorial > How to Use Server-sent Events in Node.js

How to Use Server-sent Events in Node.js

Joseph Gordon-Levitt
Release: 2025-02-08 09:31:09
Original
229 people have browsed it

How to Use Server-sent Events in Node.js

Core points

  • Server Send Events (SSE) enables the server to push data to the browser at any time, enabling functions such as real-time news reports, weather forecasts, and stock prices. The browser issues an initial request to establish a connection, and the server keeps the connection open to send a text message.
  • SSE is simpler than WebSockets, uses standard HTTP, supports one-way communication, and provides automatic reconnection. The server can terminate the SSE response at any time, but if the connection is interrupted, the browser will automatically attempt to reconnect.
  • The server can provide any number of SSE channel URLs or a single endpoint URL. Messages from the server may have associated events to identify a particular type of information. The server can also send an ID after the data line to resend any missed messages when the connection is disconnected.
  • The browser can terminate SSE communication using the .close() method of the EventSource object. The server can terminate the connection by triggering res.end() or sending a retry delay, and then return an HTTP status 204 when the same browser tries to reconnect. Only browsers can re-establish the connection by creating a new EventSource object.

This article will explore how to use Server Send Events (SSE) to enable clients to receive automatic updates from the server over an HTTP connection. We will also explore its use and show a practical demonstration of how to use Node.js to send events using a server.

  • Advantages of server sending events
  • Quick Start of Server Send Events
    • Important Tips
  • Advanced server sending event
    • Single and multiple SSE channels
    • Send different data on a single channel
    • Using data identifier
    • Specify retry delay
    • Other event handlers
    • Terminate SSE communication
  • Conclusion

Advantages of server sending events

Web Respond to HTTP messages based on request-response. Your browser issues a URL request and the server returns data. This may cause the browser to make more requests to images, CSS, JavaScript, etc., and the server responds. The server cannot actively send messages to the browser, so how does it indicate that the data has been changed? Fortunately, you can use Server Send Events (SSE) to add features such as live news releases, weather forecasts, and stock prices.

It has always been possible to use standard web technologies to achieve real-time data updates:

  • The 1990s web refreshed using full page or frame/iframe.
  • The 2000s web introduced Ajax, which can use long polling to request data and update the corresponding DOM elements with new information.

Neither of these options are ideal because the browser must trigger a refresh. If it makes requests too often, there will be no data changes, so both the browser and the server will do unnecessary work. If it requests too slowly, it may miss important updates, and the stock price you are following has plummeted!

Server Send Events (SSE) Allows the server to push data to the browser at any time:

  • The browser still makes an initial request to establish the connection.
  • The server returns an event stream response and keeps the connection open.
  • The server can use this connection to send text messages at any time.
  • Incoming data will raise a JavaScript event in the browser. The event handler function parses the data and updates the DOM.

Essentially, SSE is an unlimited data stream. Think of it as downloading an infinitely large file that is downloaded in small pieces that you can intercept and read.

SSE was originally implemented in 2006 and supports this standard in all major browsers. It may not be well known as WebSockets, but the server sends events easier, uses standard HTTP, supports one-way communication, and provides automatic reconnection. This tutorial provides example Node.js code without third-party modules, but SSE can be used in other server-side languages, including PHP.

Quick Start of Server Send Events

The following demonstration implements a Node.js web server that outputs random numbers between 1 and 1000 at random intervals of at least every three seconds.

You can find our Node.js SSE demo here.

This code uses the standard Node.js http and url modules to create a web server and parse URL:

import http from "node:http";
import url from "node:url";
Copy after login
Copy after login

The server checks for incoming URL requests and reacts when encountering the /random path:

const port = 8000;

http.createServer(async (req, res) => {

  // 获取 URI 路径
  const uri = url.parse(req.url).pathname;

  // 返回响应
  switch (uri) {
    case "/random":
      sseStart(res);
      sseRandom(res);
      break;
  }

}).listen(port);

console.log(`server running: http://localhost:${port}\n\n`);
Copy after login
Copy after login

It initially responds with the SSE HTTP event stream header:

// SSE 头
function sseStart(res) {
  res.writeHead(200, {
    Content-Type: "text/event-stream",
    Cache-Control: "no-cache",
    Connection: "keep-alive"
  });
}
Copy after login
Copy after login

Another function then sends a random number and calls itself after the random interval passes:

// SSE 随机数
function sseRandom(res) {
  res.write("data: " + (Math.floor(Math.random() * 1000) + 1) + "\n\n");
  setTimeout(() => sseRandom(res), Math.random() * 3000);
}
Copy after login
Copy after login

If you run your code locally, you can use cURL in your terminal to test the response:

$> curl -H Accept:text/event-stream http://localhost:8000/random
data: 481

data: 127

data: 975
Copy after login
Copy after login

Press Ctrl | Cmd and C to terminate the request.

Browser's client JavaScript connects to /random URI using the EventSource object constructor:

// 客户端 JS
const source = new EventSource("/random");
Copy after login
Copy after login

Incoming data triggers the message event handler, where data: the string after it is available in the .data property of the event object:

source.addEventListener('message', e => {
  console.log('RECEIVED', e.data);
});
Copy after login
Copy after login

Important Tips

  • Like Fetch(), the browser issues standard HTTP requests, so you may need to handle CSP, CORS, and have the option to pass a second { withCredentials: true } parameter to the EventSource constructor to send a cookie.
  • The server must keep a separate res response object for each connected user to send data to it. This is achieved in the above code by passing the value to the closure for the next call.
  • Message data can only be a string in the format data: nn (probably JSON). It is crucial to terminate the carriage return.
  • The server can terminate the SSE response at any time using res.end(), but...
  • When the connection is interrupted, the browser will automatically try to reconnect; there is no need to write your own reconnect code.

Advanced server sends events

SSE does not require more code than shown above, but the following sections discuss other options.

Single and multiple SSE channels

The server can provide any number of SSE channel URLs. For example:

  • /latest/news
  • /latest/weather
  • /latest/stockprice

This may be practical if a single page shows a topic, but not if a single page shows news, weather, and stock prices. In this case, the server must maintain three connections for each user, which can cause memory problems as traffic increases.

Another option is to provide a single endpoint URL, such as /latest, which sends any data type on one communication channel. The browser can indicate the topic of interest in the URL query string, such as /latest?type=news,weather,stockprice, so that the server can limit the SSE response to a specific message.

Send different data on a single channel

Messages from the server can have an associated event: which is passed above the data: line to identify a specific type of information:

import http from "node:http";
import url from "node:url";
Copy after login
Copy after login

These do not trigger the client's "message" event handler. You must add a handler for each type of event. For example:

const port = 8000;

http.createServer(async (req, res) => {

  // 获取 URI 路径
  const uri = url.parse(req.url).pathname;

  // 返回响应
  switch (uri) {
    case "/random":
      sseStart(res);
      sseRandom(res);
      break;
  }

}).listen(port);

console.log(`server running: http://localhost:${port}\n\n`);
Copy after login
Copy after login

Using data identifier

The server can also choose to send after the data: line id::

// SSE 头
function sseStart(res) {
  res.writeHead(200, {
    Content-Type: "text/event-stream",
    Cache-Control: "no-cache",
    Connection: "keep-alive"
  });
}
Copy after login
Copy after login

If the connection is disconnected, the browser sends the last ID back to the server in the Last-Event-ID HTTP header so that the server can resend any missed messages.

The latest ID is also available in the .lastEventId property of the event object of the client:

// SSE 随机数
function sseRandom(res) {
  res.write("data: " + (Math.floor(Math.random() * 1000) + 1) + "\n\n");
  setTimeout(() => sseRandom(res), Math.random() * 3000);
}
Copy after login
Copy after login

Specify retry delay

Although reconnection is automatic, your server may know that new data is not needed for a specific time period, so there is no need to retain an active communication channel. The server can send a retry: response on itself or as part of the final message, containing the millisecond value. For example:

$> curl -H Accept:text/event-stream http://localhost:8000/random
data: 481

data: 127

data: 975
Copy after login
Copy after login

After receiving it, the browser will abandon the SSE connection and attempt to reconnect after the delay time has passed.

Other event handlers

In addition to "message" and named events, you can also create "open" and "error" handlers in client JavaScript.

When the server connection is established, the "open" event will be triggered. It can be used to run other configuration code or initialize DOM elements:

// 客户端 JS
const source = new EventSource("/random");
Copy after login
Copy after login

When the server connection fails or terminates, the "error" event is triggered. You can check the .eventPhase property of the event object to see what is going on:

source.addEventListener('message', e => {
  console.log('RECEIVED', e.data);
});
Copy after login
Copy after login

Remember, there is no need to reconnect: It will happen automatically.

Terminate SSE communication

The browser can terminate SSE communication using the .close() method of the EventSource object. For example:

<code>event: news
data: SSE is great!

event: weather
data: { "temperature": "20C", "wind": "10Kph", "rain": "25%" }

event: stock
data: { "symbol": "AC", "company": "Acme Corp", "price": 123.45, "increase": -1.1 }</code>
Copy after login
The server can terminate the connection by:

  1. Trigger res.end() or send retry: delay, then
  2. Returns HTTP status 204 when the same browser tries to reconnect.

Only browsers can re-establish connections by creating a new EventSource object.

Conclusion

Server-side events provide a way to implement real-time page updates, which may be easier, more practical and lighter than Fetch()-based Ajax polling. The complexity lies in the server side. You must:

  1. Keep all user's active connections in memory, and
  2. Trigger data transfer when changes occur.

But this is completely under your control, and the extension should not be more complex than any other web application.

The only downside is that SSE does not allow you to send messages from the browser to the server (except for the initial connection request). You can use Ajax, but this is too slow for applications like action games. For proper bidirectional communication, you need WebSockets. Please see how to create a live application using WebSockets in Node.js to learn more!

The above is the detailed content of How to Use Server-sent Events in Node.js. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template