We want: Low latency, bi-directional, event driven messages. Historically called Comet
All these implementations were flawed since they failed to maintain a persistent connection with the server and receive asyncronous events directly from the server
WebSocket is a protocol providing full-duplex communication channels over a single TCP connection.
The raw implementation looks something like this:
let exampleSocket = new WebSocket("ws://www.example.com/socketserver", "protocolOne");
exampleSocket.onopen = function (event) {
exampleSocket.send("Here's some text that the server is urgently awaiting!");
};
exampleSocket.onmessage = function (event) {
console.log(event.data);
};
So what's the support for this thing?
Enables realtime, bi-directional communication between web clients and servers. It has two parts: a client-side library that runs in the browser, and a server-side library for node.js. Both components have a nearly identical API. Like node.js, it is event-driven.
Primarily uses the WebSocket protocol with polling as a fallback option, while providing the same interface. Although it can be used as simply a wrapper for WebSocket, it provides many more features, including broadcasting to multiple sockets, storing data associated with each client, and asynchronous I/O.
npm i socket.io --save
Socket.io can hook into express to learn which port to use and to serve its frontend library.
const server = app.listen(config.PORT, () => console.log(`Server listening on localhost:${config.PORT}`));
const io = require('socket.io')(server);
When a new connection happens the socket variable passed on the handler represents the newly connected user.
Any events emitted or received on socket refer only to a single user, on the other hand all events on io are broadcasted to all connected users.
io.on('connection', function (socket) {
socket.emit('an event', {data: 'some payload'}); //This event is only sent to a singular user
socket.on('another event', function(data) {
io.emit('broadcast event', data); //This event is sent to everyone (broadcasted)
});
});
Keep track and display the number of connected users.
let connected = 0;
const updateOnline = () => io.emit('online', { users: connected }); //Broadcast the number of connected users
io.on('connection', function (socket) {
//On new connection increment the number of users
connected++;
updateOnline();
socket.on('disconnect', function() {
//On disconnect decrement the number of users
connected--;
updateOnline();
});
});
First of all, we need to include the frontend library.
We'll also add some HTML to display the information.
Online users:
Then we can connect to the server and we're ready to listen and send events.
//public/js/main.js
var App = {
init: function() {
this.onlineEl = document.getElementById('online');
this.socket = io.connect('http://localhost:9090');
this.subEvents();
},
subEvents: function() {
var that = this;
this.socket.on('online', function (data) {
that.onlineEl.innerHTML = data.users;
});
}
};
App.init();
Note: We don't have ES6 on the frontend for now
Using what we just learned create the code to keep track how many clicks
in total a <button> receives, this should be in sync on all connected
clients.
Live code
Implement a click counter that counts the clicks on a <button>, this must be syncronized on all connected clients.
Websockets are often difficult to scale, specially if you broadcast.
Pusher is websockets as a service, you connect your frontent to it, connect your backend and it takes care of the communication and the scale.
What if I tell you there's a tool out there that does all of what we implemented out of the box?
Meteor it's a platform that allows you to build isomorphic real-time apps in a breeze.
Check out the repo https://github.com/martip-sainsburys/nodejs-workshop.