togethercomputer/js-eventsource
forked from launchdarkly/js-eventsource
Captured source
source ↗togethercomputer/js-eventsource
Description: EventSource client for Node.js and Browser (polyfill)
Language: JavaScript
License: MIT
Stars: 0
Forks: 0
Open issues: 0
Created: 2023-11-07T00:16:04Z
Pushed: 2024-10-17T22:21:43Z
Default branch: main
Fork: yes
Parent repository: launchdarkly/js-eventsource
Archived: no
README:
This library is a pure JavaScript implementation of the EventSource client. The API aims to be W3C compatible.
You can use it with Node.js, or as a browser polyfill for browsers that don't have native `EventSource` support. However, the current implementation is inefficient in a browser due to the use of Node API shims, and is not recommended for use as a polyfill; a future release will improve this.
This is a fork of the original EventSource project by Aslak Hellesøy, with additions to support the requirements of the LaunchDarkly SDKs. Note that as described in the [changelog](CHANGELOG.md), the API is _not_ backward-compatible with the original package, although it can be used with minimal changes.
Install
npm install launchdarkly-eventsource
Example
npm install node ./example/sse-server.js node ./example/sse-client.js # Node.js client open http://localhost:8080 # Browser client - both native and polyfill curl http://localhost:8080/sse # Enjoy the simplicity of SSE
Browser Polyfill
Just add example/eventsource-polyfill.js file to your web page:
Now you will have two global constructors:
window.EventSourcePolyfill window.EventSource // Unchanged if browser has defined it. Otherwise, same as window.EventSourcePolyfill
If you're using webpack or browserify you can of course build your own. (The example/eventsource-polyfill.js is built with webpack).
Extensions to the W3C API
All configurable extended behaviors use the optional eventSourceInitDict argument to the EventSource constructor. For instance:
var eventSourceInitDict = { initialRetryDelayMillis: 1000, maxRetryDelayMillis: 30000 };
var es = new EventSource(url, eventSourceInitDict);In a browser that is using native EventSource the extra argument would simply be ignored, so any code that will run in a browser, if it might or might not be using this polyfill, should assume that these options might or might be used.
Extensions to event behavior
Like the standard EventSource, this implementation emits the event open when a stream has been started and error when a stream has failed for any reason. All events have a single parameter which is an instance of the Event class.
The error event has the following extended behavior: for an HTTP error response, the event object will have a status property (such as 401) and optionally a message property (such as "Unauthorized").
es.onerror = function (err) {
if (err) {
if (err.status === 401 || err.status === 403) {
console.log('not authorized');
}
}
};The following additional events may be emitted:
closed: The stream has been permanently closed, either due to a non-retryable error or becauseclose()was called.end: The server ended the stream. For backward compatibility, this is not reported as anerror, but it is still treated as one in terms of the retry logic.retrying: After an error, this indicates thatEventSourcewill try to reconnect after some delay. The event object'sdelayMillisproperty indicates the delay in milliseconds.
Configuring backoff and jitter
By default, EventSource automatically attempts to reconnect if a connection attempt fails or if an existing connection is broken. To prevent a flood of requests, there is always a delay before retrying the connection; the default value for this is 1000 milliseconds.
For backward compatibility, the default behavior is to use the same delay each time. However, it is highly recommended that you enable both exponential backoff (the delay doubles on each successive retry, up to a configurable maximum) and jitter (a random amount is subtracted from each delay), so that if a server outage causes clients to all lose their connections at the same time they will not all retry at the same time. The backoff can also be configured to reset back to the initial delay if the stream has remained active for some amount of time.
var eventSourceInitDict = {
initialRetryDelayMillis: 2000, // sets initial retry delay to 2 seconds
maxBackoffMillis: 30000, // enables backoff, with a maximum of 30 seconds
retryResetIntervalMillis: 60000, // backoff will reset to initial level if stream got an event at least 60 seconds before failing
jitterRatio: 0.5 // each delay will be reduced by a randomized jitter of up to 50%
};Configuring error retry behavior
By default, to mimic the behavior of built-in browser EventSource implementations, EventSource will retry if a connection cannot be made or if the connection is broken (using whatever retry behavior you have configured, as described above)-- but if it connects and receives an HTTP error status, it will only retry for statuses 500, 502, 503, or 504; otherwise it will just raise an error event and disconnect, so the application is responsible for starting a new connection.
If you set the option errorFilter to a function that receives an Error object and returns true or false, then EventSource will call it for any error-- either an HTTP error or an I/O error. If the function returns true, it will proceed with retrying the connection; if it returns false, it will end the connection and raise an error event. In this example, connections will always be retried unless there is a 401 error:
var eventSourceInitDict = {
errorFilter: function(e) {
return e.status !== 401;
}
};HTTP redirect responses (301/307) with a valid Location header are not considered errors, and are always immediately retried with the new URL.
Setting HTTP request headers
You can define custom HTTP headers for the initial HTTP request. This can be useful for e.g. sending cookies or to specify an initial Last-Event-ID value.
HTTP headers are defined by assigning a headers attribute to the optional eventSourceInitDict argument:
Excerpt shown — open the source for the full document.