Express & Socket.io
Intro
- Express: "Fast, unopinionated, minimalist web framework for Node.js"
- Socket.io: Nice websocket abstraction
expressjs.com
socket.io
Getting started
Set up a simple Node project:
npm init
npm install --save express socket.io
npm install --save-dev nodemon
touch index.js
# edit package.json to add a start script
#
# "scripts": {
# "test": "echo \"Error: no test specified\" && exit 1",
# "start": "nodemon index"
# },
Set up Express
index.js
// dependencies
const express = require('express');
const socketio = require('socket.io');
const http = require('http');
// create an express app instance
// and an HTTP server that listens for it.
const app = express();
const server = http.Server(app);
// start the server
server.listen(3000, () => {
console.log(`express is running on port 3000`);
});
Set up Express
Now we have an Express app listening on port 3000 that does nothing but send 404s, so we need to add routes.
Routes are how we say:
"When a user asks for this, give them that"
Routes
Create and use an Express Router
// create a router and configure some routes
const router = new express.Router();
router.get('/', (req, res) => {
res.status(200).send('Hello World');
});
router.post('/', (req, res) => {
res.status(201).send('POST OK');
});
// use the router in the / namespace
app.use('/', router);
More interesting routes
Routes with parameters
// a route with a parameter
router.get('/hello/:name', (req, res) => {
res.status(200).send(`Hello ${req.params.name}`);
});
Middleware
- Middleware intercepts requests, does something and passes them on.
- The Router is middleware.
// use middleware to log all requests
app.use('/', (req, res, next) => {
console.log(`${new Date().toISOString()} ${req.method} ${req.path}`);
next();
});
// use a router so the app knows what it's doing
app.use('/', router);
Middleware
- Middleware matches the path and all sub-paths
- So / will catch every route
- /foo will catch /foo and /foo/bar/lalala
- Middleware is executed in the order it's declared
- Finish the response cycle!
- Either call next()
- Or send a response with res.send()
Middleware
A lot of the time you'll utilise third party middleware
const morgan = require('morgan');
// morgan for logging
app.use('/', morgan());
// express.static to serve our static files
app.use('/static', express.static('client'));
Back to the task at hand!
- That's how Express works in a nutshell.
- So let's get some Sockety goodness happening.
Serve our client app
Respond with a file using res.sendFile()
// send index.html
router.get('/', (req, res) => {
res.sendFile(__dirname + '/client/index.html', {}, (err) => {
if (err) {
res.status(err.status).end();
}
});
});
Enter socket.io
Pass the Express server to socket.io
// create an express app instance
// and an HTTP server that listens for it.
// pass the server to socket.io
const app = express();
const server = http.Server(app);
const io = socketio(server);
Make a client app
Some basic JS to log things to the page
// log a string
// we have a div with id #console on the page
function log(str) {
const pre = document.createElement('pre');
pre.textContent = str;
document.querySelector('#console').appendChild(pre);
}
log('now you have a console');
Connect to the socket
Connect and start logging events
// in our index.html we're adding
// <script src="/socket.io/socket.io.js"></script>
// which socket.io automatically provides us via Express
// meanwhile, in our client JS, we'll connect to that and
// start logging events...
const socket = io();
socket.on('connect', () => {
log('connected to socket');
});
socket.on('disconnect', () => {
log('disconnected from socket');
});
Connect to the socket
Log connections on the server
const io = socketio(server);
// listen for socket events
io.on('connection', (socket) => {
console.log('socket connected');
});
Finally the good stuff
Emit events from the server to the client
const io = socketio(server);
// listen for socket events
io.on('connection', (socket) => {
console.log('socket connected');
// `socket` argument is the socket connection
// to that specific client
socket.emit('message', 'hey there');
});
Finally the good stuff
And log them on the client
// messages. log them.
socket.on('message', str => {
log(str);
});
Spreading the news
Now let's emit a message to ALL clients
// listen for socket events
io.on('connection', (socket) => {
console.log('socket connected');
// `socket` is our connection to that user
socket.emit('message', 'hey there');
// tell everybody that we just connected
io.emit('message', 'someone connected');
});
But don't go overboard
Emit a message to all other clients, with broadcast
// listen for socket events
io.on('connection', (socket) => {
console.log('socket connected');
// `socket` is our connection to that user
socket.emit('message', 'hey there');
// tell everybody else that we just connected
socket.broadcast.emit('message', 'someone connected');
});
Emit whatever you want
Emit different events to do different things.
// listen for socket events
io.on('connection', (socket) => {
console.log('socket connected');
// `socket` is our connection to that user
socket.emit('message', 'hey there');
socket.emit('alert', 'KAPOW');
// tell everybody else that we just connected
socket.broadcast.emit('message', 'someone connected');
});
// this won't annoy anybody
socket.on('alert', (str) => {
alert(str)
});
Back the other way
Let's emit an event from the client to the server
// server
// listen for socket events
io.on('connection', (socket) => {
socket.on('ayo', () => {
console.log('ayo!');
});
});
// client
document.querySelector('button').addEventListener('click', (evt) => {
socket.emit('ayo');
});
Request-Response
Client to server and back again
// server
// listen for socket events
io.on('connection', (socket) => {
socket.on('ayo', (payload, callback) => {
console.log('ayo!');
callback('right back at you');
});
});
// client
document.querySelector('button').addEventListener('click', (evt) => {
socket.emit('ayo', {}, response => {
log(response);
});
});
Rooms
A simple abstraction for grouping connections
// listen for socket events
io.on('connection', (socket) => {
// join a room and tell everyone.
socket.join('secretlol');
io.to('secretlol').emit('message', {
str: 'somebody joined secretlol',
});
// or you could broadcast...
socket.broadcast.to('secretlol').emit('message', {
str: 'someone else joined secretlol',
});
});
Questions?
Express & Socket.io
By Tarun Sharma
Express & Socket.io
- 949