Skip to content

A modern, streaming server-sent events/eventsource client

License

Notifications You must be signed in to change notification settings

rexxars/eventsource-client

Repository files navigation

eventsource-client

npm versionnpm bundle size

A modern, streaming client for server-sent events/eventsource.

Another one?

Yes! There are indeed lots of different EventSource clients and polyfills out there. In fact, I am a co-maintainer of the most popular one. This one is different in a few ways, however:

  • Works in both Node.js and browsers with minimal amount of differences in code
  • Ships with both ESM and CommonJS versions
  • Uses modern APIs such as the fetch() API and Web Streams
  • Does NOT attempt to be API-compatible with the browser EventSource API:
    • Supports async iterator pattern
    • Supports any request method (POST, PATCH, DELETE etc)
    • Supports setting custom headers
    • Supports sending a request body
    • Supports configurable reconnection policies
    • Supports subscribing to any event (eg if event names are not known)
    • Supports subscribing to events named error
    • Supports setting initial last event ID

Installation

npm install --save eventsource-client

Supported engines

  • Node.js >= 18
  • Chrome >= 63
  • Safari >= 11.3
  • Firefox >= 65
  • Edge >= 79
  • Deno >= 1.30
  • Bun >= 1.1.23

Basically, any environment that supports:

Usage (async iterator)

import {createEventSource} from 'eventsource-client'

const es = createEventSource({
  url: 'https://my-server.com/sse',

  // your `fetch()` implementation of choice, or `globalThis.fetch` if not set
  fetch: myFetch,
})

let seenMessages = 0
for await (const {data, event, id} of es) {
  console.log('Data: %s', data)
  console.log('Event ID: %s', id) // Note: can be undefined
  console.log('Event: %s', event) // Note: can be undefined

  if (++seenMessages === 10) {
    break
  }
}

// IMPORTANT: EventSource is _not_ closed automatically when breaking out of
// loop. You must manually call `close()` to close the connection.
es.close()

Usage (onMessage callback)

import {createEventSource} from 'eventsource-client'

const es = createEventSource({
  url: 'https://my-server.com/sse',

  onMessage: ({data, event, id}) => {
    console.log('Data: %s', data)
    console.log('Event ID: %s', id) // Note: can be undefined
    console.log('Event: %s', event) // Note: can be undefined
  },

  // your `fetch()` implementation of choice, or `globalThis.fetch` if not set
  fetch: myFetch,
})

console.log(es.readyState) // `open`, `closed` or `connecting`
console.log(es.lastEventId)

// Later, to terminate and prevent reconnections:
es.close()

Minimal usage

import {createEventSource} from 'eventsource-client'

const es = createEventSource('https://my-server.com/sse')
for await (const {data} of es) {
  console.log('Data: %s', data)
}

Todo

  • Figure out what to do on broken connection on request body
  • Configurable stalled connection detection (eg no data)
  • Configurable reconnection policy
  • Consider legacy build

License

MIT © Espen Hovlandsdal