Abstract illustration of data flow, represented by water streaming through two distinct pipes: a narrower pipe signifying the conventional EventSource method and a wider, more adaptable pipe symbolizing the Fetch API.

Receive Server-Sent Events in Node.js: An EventSource Alternative Using Fetch API

Real-time applications depend heavily on Server-Sent Events (SSE) to maintain seamless data exchange between the server and the client. Conventionally, developers leverage the EventSource interface for receiving SSE. However, there are two main constraints with this method:

  1. It is not natively available in Node.js, requiring an additional package to function.
  2. It only supports GET requests, limiting its use cases.

In this post, we introduce an alternative, the Fetch API coupled with getReader(), which can handle SSE from both GET and POST requests. As an added benefit, as of Node.js version 18, the Fetch API comes as an experimental feature enabled by default, requiring no extra packages.

Understanding EventSource's Limitations

The EventSource API maintains a persistent connection from a client to a server, allowing real-time data updates from the server. A typical usage looks like this:

const source = new EventSource("/sse");
source.onmessage = (event) => {
  console.log("Received", event.data);
};

The primary drawback of EventSource is its exclusive reliance on GET requests. If the given API endpoint, such as /sse, is set to POST instead of GET, it won't be compatible. Moreover, EventSource isn't included in Node.js's standard library, so leveraging it necessitates adding an external package, which expands your project's dependency footprint.

The Fetch API and getReader(): A Versatile Alternative

The Fetch API in Node.js offers a compelling alternative for handling SSE with both GET and POST requests. Here's an example:

const response = await fetch("/sse", { method: "POST" });
const reader = response.body.getReader();
const decoder = new TextDecoder("utf-8");
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  console.log("Received", decoder.decode(value));
}

In this snippet, a POST request is made to the server using the Fetch API. The response's body content is read through getReader(), and a TextDecoder object decodes the received data chunks into strings. This approach handles large data sets efficiently, processing the data in chunks as it arrives.

For more information about the getReader() method, have a look at the mdn documentation.

Importantly, the Fetch API comes as an experimental feature in Node.js. It's enabled by default starting from version 18, eliminating the need for an extra package and making it an attractive choice over EventSource in Node.js.

Wrapping Up

While EventSource remains a useful tool for handling SSE with GET requests, the Fetch API and getReader() present an out-of-the-box alternative for Node.js users, enabling both GET and POST requests. The choice between the two would largely depend on your project's specific needs and architectural design. By understanding both methods, developers can make an informed choice, building more efficient and versatile real-time applications.

Bonus: ChatGPT Demo

If you want to stream the response from the ChatGPT API, have a look at the following blog post: