Implement custom retry and error handling strategies
mainYou can control the connection lifecycle and retry logic using the following callbacks:
onopen(response): Validate the response (e.g., check status codes or content-type) before parsing. Throwing an error here triggers theonerrorhandler.onmessage(msg): Handle incoming messages. You can throw an error inside this callback to trigger theonerrorhandler.onclose(): Triggered when the server closes the connection. Throwing an error here allows you to implement custom retry logic.onerror(err): The central error handler. To stop the connection entirely, rethrow a fatal error. To trigger an automatic retry, simply do nothing or return a specific retry interval.
class RetriableError extends Error { }
class FatalError extends Error { }
fetchEventSource('/api/sse', {
async onopen(response) {
if (response.ok && response.headers.get('content-type') === EventStreamContentType) {
return; // everything's good
} else if (response.status >= 400 && response.status < 500 && response.status !== 429) {
// client-side errors are usually non-retriable:
throw new FatalError();
} else {
throw new RetriableError();
}
},
onmessage(msg) {
// if the server emits an error message, throw an exception
// so it gets handled by the onerror callback below:
if (msg.event === 'FatalError') {
throw new FatalError(msg.data);
}
},
onclose() {
// if the server closes the connection unexpectedly, retry:
throw new RetriableError();
},
onerror(err) {
if (err instanceof FatalError) {
throw err; // rethrow to stop the operation
} else {
// do nothing to automatically retry. You can also
// return a specific retry interval here.
}
}
});