A streaming parser for server-sent events/eventsource, without any assumptions about how the actual stream of data is retrieved. It is intended to be a building block for clients and polyfills in javascript environments such as browsers, node.js and deno.
If you are looking for a modern client implementation, see eventsource-client.
You create an instance of the parser, and feed it chunks of data - partial or complete, and the parse emits parsed messages once it receives a complete message. A TransformStream variant is also available for environments that support it (modern browsers, Node 18 and higher).
Other modules in the EventSource family:
- eventsource-client: modern, feature rich eventsource client for browsers, node.js, bun, deno and other modern JavaScript environments.
- eventsource-encoder: encodes messages in the EventSource/Server-Sent Events format.
- eventsource: Node.js polyfill for the WhatWG EventSource API.
Note
Migrating from eventsource-parser 1.x/2.x? See the migration guide.
npm install --save eventsource-parser
import {createParser, type EventSourceMessage} from 'eventsource-parser'
function onEvent(event: EventSourceMessage) {
console.log('Received event!')
console.log('id: %s', event.id || '<none>')
console.log('name: %s', event.name || '<none>')
console.log('data: %s', event.data)
}
const parser = createParser({onEvent})
const sseStream = getSomeReadableStream()
for await (const chunk of sseStream) {
parser.feed(chunk)
}
// If you want to re-use the parser for a new stream of events, make sure to reset it!
parser.reset()
console.log('Done!')
If the server sends a retry
field in the event stream, the parser will call any onRetry
callback specified to the createParser
function:
const parser = createParser({
onRetry(retryInterval) {
console.log('Server requested retry interval of %dms', retryInterval)
},
onEvent(event) {
// …
},
})
If the parser encounters an error while parsing, it will call any onError
callback provided to the createParser
function:
import {type ParseError} from 'eventsource-parser'
const parser = createParser({
onError(error: ParseError) {
console.error('Error parsing event:', error)
if (error.type === 'invalid-field') {
console.error('Field name:', error.field)
console.error('Field value:', error.value)
console.error('Line:', error.line)
} else if (error.type === 'invalid-retry') {
console.error('Invalid retry interval:', error.value)
}
},
onEvent(event) {
// …
},
})
Note that invalid-field
errors will usually be called for any invalid data - not only data shaped as field: value
. This is because the EventSource specification says to treat anything prior to a :
as the field name. Use the error.line
property to get the full line that caused the error.
Note
When encountering the end of a stream, calling .reset({consume: true})
on the parser to flush any remaining data and reset the parser state. This will trigger the onError
callback if the pending data is not a valid event.
The parser will ignore comments (lines starting with :
) by default. If you want to handle comments, you can provide an onComment
callback to the createParser
function:
const parser = createParser({
onComment(comment) {
console.log('Received comment:', comment)
},
onEvent(event) {
// …
},
})
Note
Leading whitespace is not stripped from comments, eg : comment
will give comment
as the comment value, not comment
(note the leading space).
import {EventSourceParserStream} from 'eventsource-parser/stream'
const eventStream = response.body
.pipeThrough(new TextDecoderStream())
.pipeThrough(new EventSourceParserStream())
Note that the TransformStream is exposed under a separate export (eventsource-parser/stream
), in order to maximize compatibility with environments that do not have the TransformStream
constructor available.
MIT © Espen Hovlandsdal