Перед чтением этого рассказа настоятельно рекомендуется взглянуть на Часть 1. Клиентское приложение описано в Части 3.

Пакеты npm, связанные с сервером

Здесь ничего особенного - просто библиотека socket.io для настройки простого сервера WebSocket с использованием node JS. Также представлены все пакеты, связанные с babel, чтобы наш сервер работал со всеми функциями ES6.

Инициализация серверного приложения и основные переменные

Прежде всего нам нужно импортировать все внешние модули, необходимые для нашего сервера WebSocket - модули node http и socket.io, затем мы создаем сервер socket.io WebSocket.

import http from ‘http’;
import io from ‘socket.io’;
let socketServer = io(http);

После этого нам нужно инициализировать переменные - элементы для хранения элементов, используемых для отправки обновлений, и диапазон номеров, чтобы определить диапазон номеров, которые мы отправляем через WebSocket (давайте определим диапазон от 1 до 100). Использование этих переменных будет объяснено позже.

//items we need to send updates for
let items = [];
//numbers from one to 100
const range = 100;

Запустите сервер WebSocket для прослушивания порта 3001 локального хоста

socketServer.listen(3001, () => {
 console.log(‘listening on *:3001’);
});

Определите функции подписки и отмены подписки для добавления / удаления элемента из массива items

const unsubscribe = (id) => { //unsubscribe from selected id
 let index = items.indexOf(id);
 if (index > -1) {
  items.splice(index, 1);
  return true;
 }
return false;
};
const subscribe = (id) => { //subscribe for selected id
 let index = items.indexOf(id);
 if (index === -1) {
   items.push(id);
   return true;
 }
 return false;
};

Другая функция сгенерирует случайное число для определенного элемента.

const updateNumberMessage = () => { //update random id with number
 return {
   id: items[Math.floor(Math.random() * items.length)],
   number: Math.floor(Math.random() * range),
 };
};

Затем мы собираемся реализовать саму логику WebSocket в виде следующего набора методов. Вся логика, связанная с WebSocket, должна работать после успешного подключения клиента к серверу WebSocket.

socketServer.on(‘connection’, (socket) => {
/* all websocket-related logic lives here */
}

Когда клиент успешно подписан на обновления WebSocket, мы начинаем отправлять пакеты обновлений каждые 2 секунды (мы обновляем случайный элемент со случайным числом от 1 до 100). Если у нас есть ошибка, мы прекращаем отправку обновлений и очищаем интервал.

 socket.on(‘subscribe’, (data, fn) => {
   if (typeof data.ids !== ‘undefined’ && data.ids.length) { 
     items = data.ids;
     fn();
     if (!interval) {
        interval = setInterval(() => {
          socketServer.emit(‘update’, updateNumberMessage());
        }, 2000);
      }
   } else { //emit error message
     socketServer.emit(‘error’,
       {error: ‘Error! Malformed subscribe  package!’});
     clearInterval(interval);
   }
 });

Метод Socket.io on () вызывает обратный вызов для указанного события. Обратный вызов принимает 2 параметра - данные (отправленные как полезные данные события) и функцию, называемую обратным вызовом подтверждения, которая работает, когда клиент подтвердил получение сообщения.

Если мы получаем действие disable для одного из элементов, мы удаляем этот идентификатор из массива элементов, чтобы прекратить отправку обновлений для этого элемента. После успешного действия мы отправляем ответ, что конкретный элемент изменил свой статус на «отключен» и больше не получает обновлений.

socket.on(‘disable’, (data) => {
  if (typeof data.id === ‘undefined’) {
    return false;
  }
  if (unsubscribe(data.id)) {
    socketServer.emit(‘status’, {id: data.id, status: ‘disabled’});
  }
  return false;
});

Для действия подписки мы делаем обратное - добавляем элемент в массив и отправляем сообщение в WebSocket об успешном включении конкретного элемента.

socket.on(‘enable’, (data) => {
  if (typeof data.id === ‘undefined’) {
    return false;
  }
  if (subscribe(data.id)) {
    socketServer.emit(‘status’, {id: data.id, status: ‘enabled’});
  }
  return false;
 });

Полный код серверного приложения можно найти здесь. Чтобы протестировать серверное приложение, вытащите репозиторий, перейдите в папку сервера, запустите npm install, чтобы получить все необходимые пакеты, их вы можете запустить в режиме разработки, используя команду npm start из командной строки.