sse.js

repository·main·Indexed 20 days ago

https://github.com/mpetazzoni/sse.js

A flexible replacement for the standard JavaScript EventSource API (version 2.8.0). sse.js extends SSE capabilities by supporting custom HTTP methods (such as POST), custom headers, request payloads, and advanced auto-reconnection logic with Last-Event-ID tracking.

Tokens
4.2K
Snippets
13
Records
19
Agent score
21%

What's inside sse.js

  1. Handle events emitted by SSE

    main

    The SSE class implements the EventTarget interface and emits fully constructed Event objects. The event type corresponds to the Server-Sent Event's name.

    Each event object contains the following fields:

    • id: The event ID, or null if not present.
    • lastEventId: The last seen event ID, or an empty string if no event with an ID was received.
    • data: The unparsed event data.

    Standard lifecycle events include:

    • open: Fired when the first block of data is received.
    • error: Fired if an error occurs during the request.
    • abort: Fired when the stream is explicitly aborted by the client.
    • readystatechange: Fired when the ready state of the event source changes.
  2. Use Last-Event-ID for stream continuity

    main

    To ensure no messages are lost during reconnections, SSE can track the last received event ID and send it back to the server via the Last-Event-ID header. This is enabled by default via the useLastEventId: true option.

    You can access the current tracked ID via source.lastEventId.

    const source = new SSE("/api/events", {
      autoReconnect: true,
      useLastEventId: true,
      headers: { "Client-ID": "dashboard-1" },
    });
    
    source.addEventListener("message", (e) => {
      if (e.id) {
        console.log(`Received event ${e.id}`);
      }
    });
    
    source.addEventListener("open", (e) => {
      if (source.lastEventId) {
        console.log(`Reconnected, resuming from event ${source.lastEventId}`);
      }
    });
  3. Get started with SSE

    main

    To use SSE, instantiate it with a URL, attach event listeners, and start the stream. By default, the stream starts immediately upon instantiation.

    If you want to control exactly when the connection begins, pass { start: false } in the options and call the .stream() method manually.

    var source = new SSE(url);
    source.addEventListener("message", function (e) {
      // Assuming we receive JSON-encoded data payloads:
      var payload = JSON.parse(e.data);
      console.log(payload);
    });
  4. Install and Import SSE

    main

    You can use sse.js as a direct replacement for the native EventSource API. It is a fully compatible polyfill.

    Module context:

    import { SSE } from "./sse.js";

    Non-module context:

    (async () => {
      const { SSE } = import("./sse.js");
      window.SSE = SSE;
    })();

    To use it as a drop-in polyfill for existing code that relies on the global EventSource constructor, you can assign it directly:

    EventSource = SSE;
    import { SSE } from "./sse.js";
  5. Configure Auto-reconnect functionality

    main

    You can enable automatic reconnection when a connection is lost or an error occurs using the following options:

    • autoReconnect: Set to true to enable.
    • reconnectDelay: Time in milliseconds to wait before retrying (default: 3000).
    • maxRetries: Maximum number of attempts. Set to null for unlimited retries.
    • useLastEventId: If true, the last received event ID is sent in the Last-Event-ID header on reconnection (recommended).

    Auto-reconnect is automatically disabled when calling .close() or when maxRetries is reached.

    var source = new SSE(url, {
      autoReconnect: true,
      reconnectDelay: 3000,
      maxRetries: null,
      useLastEventId: true,
    });
  6. Configure auto-reconnect behavior

    main

    When autoReconnect is enabled, SSE will automatically attempt to reconnect after a connection loss or error. You can fine-tune this behavior using the following options in the constructor:

    • autoReconnect: (boolean) Enable/disable automatic reconnection.
    • reconnectDelay: (number) Milliseconds to wait between reconnection attempts.
    • maxRetries: (number) Maximum number of attempts before giving up.
    • useLastEventId: (boolean) If true, sends the Last-Event-ID header to resume the stream.

    Auto-reconnect is disabled if maxRetries is reached or if close() is called explicitly. The retryCount property tracks current attempts and resets to 0 upon a successful connection.

    const source = new SSE("/events", {
      autoReconnect: true, // Enable automatic reconnection
      reconnectDelay: 5000, // Wait 5 seconds between attempts
      maxRetries: 3, // Only try 3 times before giving up
      useLastEventId: true // Send Last-Event-ID to resume stream
    });
    
    source.addEventListener("error", () => {
      if (source.maxRetries && source.retryCount >= source.maxRetries) {
        console.log("Max retries reached, connection permanently closed");
      } else if (source.autoReconnect) {
        console.log(`Connection lost, will retry in ${source.reconnectDelay}ms`);
        console.log(`Attempt ${source.retryCount + 1}${source.maxRetries ? '/' + source.maxRetries : ''}`);
      }
    });
  7. Understand SSE readyState values

    main

    The readyState property indicates the current status of the connection. You can monitor this via the readystatechange event.

    ConstantValueDescription
    SSE.INITIALIZING-1The instance is being created.
    SSE.CONNECTING0The connection is currently being established.
    SSE.OPEN1The connection is open and streaming.
    SSE.CLOSED2The connection is closed.
  8. Handle reconnection manually

    main

    If you prefer not to use autoReconnect: true, you can implement your own reconnection logic by listening to the error or abort events and calling .stream() manually.

    const source = new SSE(url, { autoReconnect: false });
    
    source.addEventListener("error", (e) => {
      console.log("Connection lost");
      // Wait a bit then reconnect
      setTimeout(() => {
        source.stream();
      }, 3000);
    });
    
    // Or reconnect on abort
    source.addEventListener("abort", () => {
      source.stream();
    });
  9. Listen for specific event types

    main

    SSE allows for arbitrary event types via the event field in the server response. While the default type is message, you can listen for custom types using addEventListener or the on<event> property syntax. If both are defined, the on<event> handler is called first.

    // Using addEventListener
    var source = new SSE(url);
    source.addEventListener("status", function (e) {
      console.log("System status is now: " + e.data);
    });
    source.stream();
    
    // Using on<event> style
    var source = new SSE(url);
    source.onstatus = function(e) { ... };
  10. Access response headers and status codes

    main

    When the open event is fired, you can access the server's response status code and headers. The headers property is a map where keys are lowercased header names and values are arrays of strings.

    var source = new SSE(url);
    source.addEventListener("open", function (e) {
      console.log(
        "Got a " + e.responseCode + " response with headers: " + e.headers
      );
    });
    source.stream();