Categories
Node.js Basics

Node.js Basics — Socket.io

Spread the love

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

Real-Time Communication with Socket.io

Socket.io is a real-time communication library that combines HTTP requests with WebSockets to enable real-time communication in our app.

For example, we can create a simple app with Socket.io by writing:

index.js

const content = require('fs').readFileSync(__dirname + '/index.html', 'utf8');

const httpServer = require('http').createServer((req, res) => {
  res.setHeader('Content-Type', 'text/html');
  res.setHeader('Content-Length', Buffer.byteLength(content));
  res.end(content);
});

const io = require('socket.io')(httpServer);

io.on('connect', socket => {
  console.log('connect');
});

httpServer.listen(3000, () => {
  console.log('go to http://localhost:3000');
});

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Minimal working example</title>
</head>

<body>
  <ul id="events"></ul>

<script src="/socket.io/socket.io.js"></script>
  <script>
    const $events = document.getElementById('events');

    const newItem = (content) => {
      const item = document.createElement('li');
      item.innerText = content;
      return item;
    };

    const socket = io();

    socket.on('connect', () => {
      $events.appendChild(newItem('connect'));
    });
  </script>
</body>

</html>

In index.js , we server the index.html file.

Also, we listen to the connect event to listen to any connections that are made from the client side.

In index.html , we make the connection.

We call socket.on to listen to connect event to add the item when we connect to the Socket.io server.

Installation with Express

We can use Socket.io with an Express app.

To do that, we can write:

index.js

const express = require('express');
const app = express();
const server = require('http').createServer(app);
const options = { /* ... */ };
const io = require('socket.io')(server, options);

io.on('connection', socket => {
  console.log('connect')
});

app.use(express.static('public'));

app.get('/', (req, res) => {
  res.sendFile(`${__dirname}/index.html`);
});

server.listen(3000);

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Minimal working example</title>
</head>

<body>
  <ul id="events"></ul>

  <script src="/socket.io/socket.io.js"></script>
  <script>
    const $events = document.getElementById('events');
    const newItem = (content) => {
      const item = document.createElement('li');
      item.innerText = content;
      return item;
    };
    const socket = io();
    socket.on('connect', () => {
      $events.appendChild(newItem('connect'));
    });
  </script>
</body>

</html>

We use the same index.html file as before.

The only difference is that we serve it with express.

We call http module’s createServer method with the Express app instance instead of using a callback with it.

Then we serve the static file with the res.sendFile method.

Namespace

We can create namespaces to segregate communication traffic.

For example, we can write:

index.js

const express = require('express');
const app = express();
const server = require('http').createServer(app);
const options = { /* ... */ };
const io = require('socket.io')(server, options);

io.on('connection', socket => {
  console.log('connect')
});

const adminNamespace = io.of('/admin');

adminNamespace.use((socket, next) => {
  console.log(socket);
  next();
});

adminNamespace.on('connection', socket => {
  socket.on('delete user', (data) => {
    console.log(data);
  });
});

app.get('/', (req, res) => {
  res.sendFile(`${__dirname}/index.html`);
});

server.listen(3000);

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Minimal working example</title>
</head>

<body>
  <ul id="events"></ul>

  <script src="/socket.io/socket.io.js"></script>
  <script>
    const socket = io('/admin');
    socket.emit('delete user', 'foo')
  </script>
</body>

</html>

In the index.js file, we created the /admin namespace with:

const adminNamespace = io.of('/admin');

Then we call the use method with our own middleware function before we listen for the connections to the namespace.

We can add our logic to allow or deny the connect within the use callback.

We call next to finish the connection.

The adminNamespace.on method watches the connection event to watch for connections to the namespace.

Then we call socket.on with the event name we want to listen to and then get the data from the data parameter.

In index.html , we call io('/admin') to connect to the '/admin' namespace.

Then we call socket.emit with the event name as the first argument and the event data as the 2nd argument.

Conclusion

We can do real-time communication with Socket.io easily.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *