SocketCluster. The most underrated framework. Part 2: A simple example
Tags: javascript, node, opensource, socketcluster
Published: 2021-03-30 19:16:35

{% github maarteNNNN/sc-underrated-framework-part2 %}

# Part 2: A simple example

## Recap

In [Part 1](https://dev.to/maartennnn/socketcluster-the-most-underrated-framework-part-1-intoduction-562p) we gave an introduction to what SocketCluster is, does and which projects/companies use it.

## Setting up the SocketCluster project.

> **NOTE**
> In this article I will focus solely on SocketCluster and not implement Vue yet. We will do some vanilla client js in the `index.html` file served by SocketCluster.

We'll need the `socketcluster-cli` to be able to scaffold a project. Install it by executing `npm i -g socketcluster`. Initiating a project can be done with `socketcluster create <project-name>`. Let's open our code editor and take a look at what we have. The project consists of two directories `kubernetes` and `public` and some files. `kubernetes` is where all the config files to deploy as a `kubernetes` service. We will discuss this in a later article. `public` is a directory served by Express and upon firing up SocketCluster it will be accessible by navigating [localhost:8000](http://localhost:8000). Let's fire up SocketCluster and see what we can do by running `npm run start`. The default port is `8000`.

Let's take a look where the magic happens. The `server.js` file. The `server.js` consists of some sections, the beginning are mostly constants to environment variables. Then it creates two servers. One is the `httpServer` and the other is the `agServer`. The `agServer` handles the sockets. The `httpServer` is a HTTP server wrapped in [eetase](https://github.com/SocketCluster/eetase). Which basically adds a request to a queue to be able to run `for await (let ... of asyncQueueIterable) { ...logic... }` loop on the requests. Then comes the Express part. It defines which directory to serve and provides a `/health-check` route to see if the server is operational.

```js
// HTTP request handling loop.
(async () => {
  for await (let requestData of httpServer.listener('request')) {
    expressApp.apply(null, requestData);
  }
})();
```

This piece of code [calls](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call) every request asynchronously to the `expressApp` variable and passes the requestData as the first argument, basically handling the request. This is where the `eetase` comes in handy to queue up requests and carefully execute them one by one.

## Let's create an endpoint

We will create an endpoint in the `server.js` first. This is the entrypoint for every socket connection. Let's add some code:

```js
for await (let { socket } of agServer.listener('connection')) {
...
  for await (let request of socket.procedure('test')) {
    console.log(request.data);
    request.end({ message: 'Data received, thanks client!' });
  }
...
}
...
```

This will handle any request on the `test` procedure. Log the given data to the console and respond with the message `Data received, thanks client!`.

Now let's add some code to actually test this route on the client. Let's use the `index.html` in the `public` folder so we can do some basic testing. Add a button below the `iframe` block in the HTML:

```html
...
<!-- IFRAME BLOCK -->
<button onclick="send()">Test</button>
...
```

And add some JavaScript logic below `let socket = socketClusterClient.create();`

```js
const send = async () => {
  console.log('sending to the server...');
  const response = await socket.invoke('test', {
    message: 'This is our first message from the client to the server',
  });
  console.log(response);
};
```

Restart the server and go to [localhost:8000](http://localhost:8000), open your developer console and hit the button `Test`. Upon clicking you should receive the `Data received, thanks client!` in the browser and when going to the terminal it should show `This is our first message from the client to the server`.

Now you succesfully created an endpoint from the `client` to the `server`. Now you can do some cool things but let me show you that you can do it the other way around as well. Unlike REST, SocketCluster lets you handle messages both from the `server` to the `client` as well as from the `client` to the `server`. Let's make a quick example sending an `interval` to the client.

On the server we will add the `interval` of 10 seconds:

```js
...
const send = async () => {
  console.log('sending to the server...')
  const response = await socket.invoke(
    'test',
    { message: 'This is our first message from the client to the server' },
  );
  console.log(response)
}

setInterval(async () => {
  console.log('sending data to client...');
  const data = await socket.invoke('from-server', {
    message: 'This is sent from the server to the client',
  });

  console.log(data);
}, 10000);
...
```

And on the client we will listen to the procedure:

```js
...
const send = async () => {
  console.log('sending to the server...')
  const response = await socket.invoke(
    'test',
    'This is our first message from the client to the server',
  );
  console.log(response)
}

(async () => {
  for await (let request of socket.procedure('from-server')) {
    console.log(request.data);
    // return this message to the server, it could just be request.end() to terminate it
    request.end({ message: 'Thanks server, message received' });
  }
})();
...
```

Restart the server and refresh the browser window. You should receive the message `This is sent from the server to the client` every 10 seconds.