🎓 background

During the interaction between the browser and the server, the server communicates with the browser. For example, the server asynchronously processes the information and pushes the information to the browser.

However, not all background services have established websocket channels, so the common practice is to periodically query the browser, polling background data.

From a request point of view, polling is not concise and elegant because it is unnecessary for the browser to initiate a handshake and send a packet to the background service.

Is there a way that doesn’t require a WebSocket channel and doesn’t require polling to be “low”? SSE (Server-site Events) introduced in this article is concise and elegant enough.

🤔 ️ SSE is what

SSE stands for Server-sent Events. It is a way for a Server to push data to a client.

The essence of SSE is to continuously send streaming information through HTTP request, so that the server pushes information to the client. Similar to video streaming.

It is not a one-time packet, but will always wait for the server to push. So the client doesn’t close the connection and wait for the server to push it. This enables the server to push to the client.

🆚 SSE VS Websocket

Websocket is two-way communication (full duplex), where browsers <-> servers communicate with each other, making it more powerful and flexible.

SSE is one-way communication (half duplex), browser <- server, essentially downloading information.

contrast advantages disadvantages
Websocket 1. Full duplex with more powerful functions

1. The server needs to be supported again because it is complex

2. Reconnection requires additional deployment
SSE 1. The protocol is lightweight, and the server that supports HTTP supports it

2. Convenient reconnection is supported by default

3. Supports custom data types
1. Half-duplex is not flexible enough

Both have their own characteristics and are suitable for different places

💡 Use of SSE

Since SSE works on both client and server, the apis are divided into client and server.

Browser usage

Check whether it can be used

SSE’s API in the browser is on the EventSource object. In general, except for IE Edge, all major browsers support:

if (Boolean(window.EventSource)) {
  // ...
}
Copy the code

Establish a connection to the server

The browser creates an EventSource instance and then initiates a connection to the server.

Of course, the URL can be in the same domain as the current url, or it can be cross-domain.

/ / the same url
let source = new EventSource(url);

// Take cookies across domains. Open the withCredentials property to indicate whether cookies are sent together.
let source = new EventSource(url, { withCredentials: true });
Copy the code

Change of state

The readyState property in the EventSource instance indicates the current connection state. You can take the following values.

The values explain
0 Indicates that the connection is not established, or the disconnection is being reconnected
1 Indicates that the connection has been established and data can be accepted
2 Indicates that the connection is broken and will not be reconnected

The basic use

  • When establishing a connection, will triggeropenEvents, andjsThe usage of other events is basically the same
/ / onopen method
source.onopen = (event) = > {
    // ...
}

// addEventListener
source.addEventListener('open'.(event) = > {
  // ...
}, false);
Copy the code
  • When the message is received, will triggermessageEvents, andjsThe usage of other events is basically the same.
/ / the onmessage method
source.onmessage = (event) = > {
  const data = event.data;
  // ...
};

// addEventListener
source.addEventListener('message'.(event) = > {
  // Data is the data returned by the server. It is in text format
  const data = event.data;
  // ...
}, false);
Copy the code
  • When an error occurs(for example, interrupt)errorEvents, andjsThe usage of other events is basically the same.
/ / onerror method
source.onerror = (event) = > {
  // ...
};

// addEventListener
source.addEventListener('error'.(event) = > {
  // ...
}, false);
Copy the code
  • Close the connection
source.close();
Copy the code
  • Custom events, which is triggered by defaultmessageEvent, but you can also customize the event so that it does not firemessageEvents. This example toinfoEvent listening
source.addEventListener('info'.(event) = > {
  const data = event.data;
  // ...
}, false);
Copy the code

Use of the server

Request header

The data the server sends to the browser is utF-8 encoded text, and the HTTP header has specific information. You must specify the content-type as event-Steam.

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Copy the code

The data format

A message sent each time consists of several messages separated by \n\n. The types are as follows:

/ / data column
data: [value]\n

// Customize the information type
event: [value]\n

// Data identifier
id: [value]\n

// Maximum interval
retry: [value]\n

/ / comment
: [value]\n

Copy the code
contrast describe example
data Data content is represented by data, which can take up one or more lines and end with “\n\n” data: begin message\n

data: continue message\n\n
event The event header indicates a custom data type, default if nomessageThe event event: foo\n

data: a foo event\n\n
id Data identifiers are represented by IDS, which correspond to the number of each piece of data id: msg1\n

data: message\n\n
retry By default, the browser does not send any message for three seconds to start reconnection. It can be used on the server sideretryHeader information that specifies the maximum interval for communication retry: 10000\n
Typically, the server sends a comment to the browser every once in a while to keep the connection going : This is a comment

Server-side implementation

Each server implementation is different. Here is the NodeJS solution implementation.

NodeJS implementation

// sse.js
const http = require("http");const http = require("http");

http.createServer(function (req, res) {
  res.writeHead(200, {
    "Content-Type": "text/event-stream"."Cache-Control": "no-cache"."Connection": "keep-alive"."Access-Control-Allow-Origin": The '*'}); res.write("retry: 1000\n");
  res.write("event: connecttime\n");
  res.write("data: " + (new Date()) + "\n\n");

  interval = setInterval(function () {
    res.write("data: " + (new Date()) + "\n\n");
  }, 1000);

  req.addListener("close".function () {
    clearInterval(interval);
  }, false);
}).listen(8080);
Copy the code

Startup and access

Just need Node sse.js to open it

node sse.js
Copy the code

And visit http://127.0.0.1:8080/ to access sse’s page!

🔚 epilogue

From polling to SSE, and then to SSE and Websocket technology selection, different scenarios with different schemes. There are long obstacles on the way to have it both ways.

Development is the same as growth. First “grow up”, then “grow up fast”, and finally “grow up well”. The development process is the same, replacing the string “grow” with “iterate”. The process is essential and the experience is completely different.

Hope to bring you some help, thank you for your time to read here ❤️.

Plus: Welcome to my blog