How to connect to a web socket server 🔥 in Javascript using laravel echo 
Tags: javascript, websockets, laravel, laravelecho
Published: 2021-12-09 07:28:17

## Web sockets?
Web sockets help a client application to receive events from a server application without asking the server for new information every few seconds, rather the server sends the client new information whenever it happens.

### How do web sockets worker.
In simple terms, the following sequence of events happens,
1. The server creates a channel, which can either be public, private or a presence channel.
`Public` channels can be connected to by anyone, `private` and `presence` channels require authentication to connect but presence channels allow channel members to see other members of the channel.
2. After a channel has been created, a client application wishing to receive events, connects to that channel using the channel name. The client can be any application, android, ios or web app that can implement the `ws` protocol.
3. The client application then listens to a particular event from a connected channel, using the event name.
4. Then whenever a server has new information to publish, it publishes an event with a particular name over a specified channel.
5. In turn the client application will receive this information without having to query the server for that information.

### How do i connect to a web-socket server?
In order to receive events from a particular server, client applications usually connects to a third party server , which publishes messages on behalf of the original server. All the original server application has to do is to create channels on the third party server, the just publish event messages to that server, which frees the original server from the budden of dealing with web socket connections from clients.
> Two of the most common third party servers for dealing with websockets are `pusher` and `ably`. All demostrations in this guide will use ably, but its the same thing for pusher and other custom websocket implementations.

So the client application connects to a channel on the ably or pusher websocket server, and the listens to events.

### How to connect to ably from a javascript application. Vannilla js, Vue js or React Js
Connections to websocket servers is usually done using the `ws` protocol implemented by most browsers, but it would be in my opinion somehow complex to do a websocket implementation from scratch using the protcol. An approach i like to use is to **"Donot reinvent the wheel"** by using a websockets library.

**Which library ?**
- The Laravel echo js library is a good option for most applications. So i will show sample code of how to connect to both public and private channels in a javascript application using the laravel echo library.

### How to use laravel echo library?
For laravel echo to work, you will need to use the `pusher-js` library. There for you will have to install both echo and pusher js. Here are the steps for setting up the echo library to use web sockets.

1. Step 1: Initiate a js application. The js app can be vanilla, vue or react. Here i will destrate using vue.js.

2. Step 2: Install the laravel-echo and pusher-js libraries.
    - install pusher-js and laravel echo
       ```
        npm install pusher-js
        npm install laravel-echo
       ```

3. Step 3: Create an instance of laravel echo. In your entry js file ie `main.js`, create an instance of echo an attach it to the window. 
- Import laravel echo
    >  import Echo from 'laravel-echo';
- Import pusher-js and attach it to the window.
    >  window.Pusher = require('pusher-js');
- Create an instance of laravel echo and attach it to the window.

        window.Echo = new Echo({
        broadcaster: 'pusher',
        key: "Kp8mUw.DDCTHQ",//app public key: format='APP_KEY.APP_ID'
        wsHost: 'realtime-pusher.ably.io',
        wsPort: 443,
        disableStats: true,
        encrypted: true,`
        })

    **Meaning of params:**
    - broadcaster: the broadcaster is the protocol used to broadcast the messages which is pusher in this case.
    - key: for websockets as service servers such as ably, you will need to provide the public key of the app from which you will receive events. the format of the key is `APP_KEY:APP_ID`, both are available in the ably dashboard.
    - wsHost: the ip address or hostname of the web sockets server. 
    - wsPort: the port on which to connect to the web socket server. 

    > For public channels, the above code is enough to initiate a connection to a web socket server. However for private channels, the original application server will need to provide some form of authentication to those channels. Therefore when intiating laravel echo, you need to provide an `authEndpoint` or an `authorizer` function incase of a custom authentication setup.

    **Sample of laravel echo intialization code for private channels.**


        const baseUrl = 'http://localhost:8000/api';
        const token = "Bearer eyJ0eXAiOiJ..."; // app bearer login token for apis 
        const apiKey = "application key"; // api key,for apis that require api keys

        window.Echo = new Echo({
        broadcaster: 'pusher',
        key: "Kp8mUw.DDCTHQ",//app public key: format='APP_KEY.APP_ID'
        wsHost: 'realtime-pusher.ably.io',
        wsPort: 443,
        disableStats: true,
        encrypted: true,
        // authEndpoint: `${baseUrl}/broadcasting/auth`,
        authorizer: (channel) => {
            return {
                authorize: (socketId, callback) => {
                    axios.post(`${baseUrl}/broadcasting/auth`, {
                        socket_id: socketId,
                        channel_name: channel.name
                    },
                    {
                        headers: {
                        'Authorization': token,
                        'key': apiKey, 
                        }
                    }
                    )
                    .then(response => {
                        callback(false, response.data);
                    })
                    .catch(error => {
                        callback(true, error);
                    });
                }
            };
        },

    > The authEndpoint on the application server needs to return authenticated or unauthenticated depending on wether the user is authorized or not.

4. Step 4: Connect to a channel. After initiating a web socket connection, the client application has connect to a specific channel.
    - public channel: Using echo, here is how you connect to a public channel.
        >     window.Echo.channel('status-updated')

        Here `status-updated` is the name of the channel,
    - Private channel: To connect a private channel, use `private` instead of `channel`.
    
            window.Echo.private(`bulk-upload-channel.${this.batch.id}`) 
        The `${this.batch.id}`represents avariable part of the channel name.

5. Step 5: Listen to events. Using laravel echo, both public and private use the same method to listen to events. the `listen` method.

        .listen('.updated', (e) => {
            console.log("event received")
            console.log(e)
        })

    `updated` is the name of the event, but it should be writen as `.updated`. Note the dot `.` infront of the word updated , it is required when using custom channel names.

    So to to connect to a channel and to listen to events, here is the full snippet.

        window.Echo.channel('status-updated')
        .listen('.updated', (e) => {
            console.log("event received")
            console.log(e)
        })

    > The `e` param, contains all information and data about the event.

**Note :** 
Though i have only tested it with a vue js app, i believe the above steps, should work for all javascript implementations.  
Also, i have only tested using a laravel powered server that uses ably , but the same should work even for pusher or the community pusher replacement.

**Github repository**. All the code can be found in the github repository here. [Web sockets client demo repository](https://github.com/kamasuPaul/websockets-client-demo)