Search code examples
javascriptnode.jsexpressserver-sent-events

How to send 'text/event-stream' data from express.js?


Trying to get a basic server-sent-event working with express.js on server side:

index.js:

const app        = require('express')();
const index_html = require('path').join(__dirname, 'index.html');

app.get('/', (req, res) =>
{
    res.sendFile(index_html);
});

app.get('/data', (req, res) =>
{
    res.header('Cache-Control', 'no-cache');
    res.header('Content-Type', 'text/event-stream');

    setInterval(() =>
    {
        res.write(new Date().toISOString() + '\n\n');
    }, 1000);
});

app.listen('7000');

index.html:

<!doctype html>
<head>
    <title>Hello World</title>
</head>
<body>
    <h1 id='result'>No Data Yet</h1>
    <script>
    var source = new EventSource('data');
    source.onmessage = function(event)
    {
        console.log('invoked');
        document.getElementById('result').innerHTML = event.data + '<br>';
    };
    </script>
</body>

The source.onmessage never triggers.


Solution

  • Server side events need to send data in a particular (text) format, specifically, to send data, you need a line of text in the format

    data: text to send goes here
    

    other types of data in a single event can be type, id, and retry

    any line that doesn't start with

    data:
    type:
    id:
    retry:
    

    is ignored, hence why you were not getting any events

    simple change

    setInterval(() =>
    {
        res.write('data: ' + new Date().toISOString() + '\n\n');
    }, 1000);
    

    Though, I'd write it like

        setInterval(() => res.write(`data: ${new Date().toISOString()}\n\n`), 1000);
    

    Further reading MDN documentation