Server Sent Events

LIVE UPDATES WITH

JavaScript community

Agenda

  • Server Sent Events standard
  • How it works
  • Compare with WebSocket / Long Polling
  • Browser Support
  • Use cases
  • EventSource API
  • Example using Node.js (Express) and Vue.js

Wait, Vue ?

Why Vue ?

46 % developers want to learn it, but didn't try

Server Sent Events standard

Server-Sent Events (SSE) is a server push technology enabling a browser to receive automatic updates from a server via HTTP/2 (HTTP/1.1) connection.

Server Sent Events

Is this a WebSocket ?

How it works

The server receives a regular HTTP request from the client.

Every time that the server writes an event to the HTTP response, the client will receive it and process it in a listener callback function

The client creates a new JavaScript EventSource object, passing it the URL of an endpoint which is expected to return a stream of events over time.

1

2

3

Benefits of HTTP/2

  • HTTP/2 is backwards compatible with HTTP/1
  • Multiplexing — Multiple Requests per Connection
  • Prioritization — Loading Essential Resources First
  • HPACK Compression — Reducing Junk in Headers

Compare with other Approaches

WebSocket

WebSocket

  • No reconnection by default
  • Custom authentication logic
  • Scaling problems
  • More app complexity

SSE

  • Reconnection out of the box
  • HTTP authentication 
  • No scaling problems
  • Easy to use

Except one thing...

SSE is unidirectional. When you open a SSE connection, only the server can send data to the client (browser, etc.). The client cannot send any data.  

Solution: HTTP requests + EventSource

“I don’t care about your “Server-Sent stuff”, I will request every half a second!”

HTTP Polling

SSE

  • Simpler implementation and Data efficiency
  • It is automatically multiplexed over HTTP/2 out of the box
  • Limits the number of connections for data on the client to one
  • SSE provides a memory-efficient implementation of XHR streaming. Unlike a raw XHR connection, which buffers the full received response until the connection is dropped, an SSE connection can discard processed messages without accumulating all of them in memory.
  • Polling responses can’t really be in sync
  • Polling requiring 3 round-trips (TCP SIN, SSL, and Data)
  • Timeouts (Connection getting closed by the proxy server if it remains idle for too long)

Browser Support

Can I Use ...

Make it work on IE & Edge !

Use Cases

A few simple examples of applications that could make use of Server-Sent Events:

  • A real-time chart of streaming stock prices
  • Real-time news coverage of an important event (posting links, tweets, and images)
  • A live Github / Twitter dashboard wall fed by Twitter’s streaming API
  • A monitor for server statistics like uptime, health, and running processes.

EventSource API

The EventSource interface

To enable servers to push data to Web pages over HTTP or using dedicated server-push protocols, this specification introduces the EventSource interface.

  created() {
    const receiveMessage = this.receiveMessage;
    const eventSource = new EventSource("http://localhost:3000/event-stream");
    eventSource.onmessage = function(event) {
      console.log("New message", event.data);
      receiveMessage(JSON.parse(event.data));
    };
  }

Client-side implementation

Note: event.data is a string, so we need to parse it and convert to object

const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');

const app = express();

app.use(cors());
app.use(bodyParser.json());

app.get('*', (req, res) => res.send('OK'));

app.get('/sse', (req, res) => {
    // create SSE connection
});

app.listen(3000, () => console.log('server started...'));

Server-side implementation

app.get('/sse', (req, res) => {
    // SSE Setup
    res.writeHead(200, {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive',
    });
    
    res.write('\n');

    let messageId = 0;

    const intervalId = setInterval(() => {
        res.write(`id: ${messageId}\n`);
        res.write(`data: Test Message -- ${Date.now()}\n\n`);
        messageId += 1;
    }, 1000);

    req.on('close', () => {
        clearInterval(intervalId);
    });
});

SSE Controller

function createConnections() {
    let list = [];

    return {
        send(message) {
            messageId++;
            list.forEach(({ id, req, res }) => {
                console.log('Sending for: ', id)
                res.write(`id: ${messageId}\n`);
                res.write(`data: ${JSON.stringify(message)}\n\n`);
            });
        },
        add(id, req, res) {
            list.push({ id, req, res })
        },
        remove(id) {
            list = list.filter(item => item.id !== id);
        }
    }
}

How to manage connections ?

Or you can use events.js

Live Coding

Thank you!

Link to slides:

Live Updates with Server Sent Events

By Vladimir Vyshko

Live Updates with Server Sent Events

  • 454