# Web Socket

ExpressWebJS offers a robust WebSocket Provider to serve real-time apps.

The server works on pure WebSocket connections (supported by all major browsers) and scales naturally within a cluster of Node.js processes.

# Basic Example

Let’s build a single room chat server for user messaging.

  node maker make-ws-controller chatController

This will generate our chatController class inside App/Http/Controller/Ws directory. Our chatController class looks like this:

"use strict";
const WsBaseController = require("@WsBaseController");

class chatController extends WsBaseController {
  constructor(socket) {
    super(socket);
    this.socket = socket;
  }
  onMessage(data) {
    // same as: socket.on('message')
    this.socket.emit("message", data);
    console.log(data);
  }
  close() {
    // same as: socket.on('close')
  }
  onError() {
    // same as: socket.on('error')
  }
}

module.exports = chatController;

Next we config WebSocket options in App/Config/socket.js file.

# WebSocket Route.

We will now setup our websocket route pointing to our chatController we already created. Web socket route is located at Routes/socket.js file.

"use strict";

/*
|--------------------------------------------------------------------------
| socket.io
|--------------------------------------------------------------------------
|
| This file is used to register socket.io channels and start the Ws server.
|
*/

const Ws = require("@socket.io");

Ws.channel("chat", "chatController");

Now our chat channel is now linked to our chatController in App/Http/Controller/Ws directory.

With everything ready, we can now start emitting messages to our channel by requiring socketBox in our code.

Let say in our product event listener, we want to emit to our websocket, we can do that like so:

"use strict";
let emitter = require("@emitter");
let socketBox = require("@socketBox");

class ProductListener{
  /**
   * Handle the event.
   * @param {string} eventName
   * @param {object} data
   */
  constructor(eventName, data) {
    emitter.once(eventName, () => {
      socketBox.emit("room", "chat");
      socketBox.emit("message", data); 
  }
}

module.exports = ProductListener;

# Event Methods

class ChatController {
    onMessage () {
        // same as: socket.on('message')
    }
    onClose () {
        // same as: socket.on('close')
    }
    onError () {
        // same as: socket.on('error')
    }
}

To keep things simple we won’t store user messages, just deliver them. Open the Routes/sockets.js file and paste the following code:

const Ws = require("@socket.io");
Ws.channel("chat", "chatController");

We can also bind a closure to the Ws.channel method, but having a dedicated controller is the recommended practice.

# Client Code

Let’s switch from server to client and subscribe to the chat channel.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Socket.io test</title>
</head>
<body>
    <script src="http://localhost:5000/expressweb-ws/socket.io.js"></script>
    <script>
    const socket = io.connect("http://localhost:5000/", {
        path: "/expressweb-ws",
    });
    socket.to('chat').emit("message", [{ name: "Welcome to my Chat room" }]);
    socket.on("message", (data) => {
        console.log(data);
    });
    </script>
</body>
</html>