Easy pub/sub channels/messaging with ES6 and Websockets!

I didn't want to pull in a library to get "message types" or "channels" for my messages between the browser and NodeJS. Out of playing around, I think I discovered something beautiful. It is easy to understand and extend. Sure it doesn't have caching or anything fancy, and is definitely not for enterprise software, but if you need only something simple for pub/sub channels, I think this is perfect! So great that I just had to share it.

On server-side:

const wss = new WebSocketServer({ port: 9001 })

wss.on('connection', (ws) => {
    ws.on('message', (datastr) => {
        const data = JSON.parse(datastr)

        [

             require('accounts').totalAccounts,
             require('accounts').findAccount,
             require('pages').getTitles
        ]
        .filter(f => f.name === data.type)
        .map(r => r(data, (result) => {
             ws.send(JSON.stringify({
                 type: data.type,
                 result
             }))
        }))

    })

})
On client-side:

ws = new WebSocket('wss://127.0.0.1:9001')

ws.onopen = () => {

    ws.send(JSON.stringify({
        type: 'totalAccounts'
    })
}

ws.onmessage = (datastr) => {

        const data = JSON.parse(datastr)

        [

             totalAccounts,
             findAccount,
             getTitles
        ]
        .filter(f => f.name === data.type)
        .map(r => r(data.result))
}

function totalAccounts(result) {

      document.querySelector('#accounts').innerHTML = result;
}

/* 

  ...and so on! 

  You could use webpack to use require()
*/



Someone requested I do a little explanation, so I'm copying what I wrote on Reddit to over here. I initially thought it would be better to let readers try and figure out what is happening on their own.

Basically a message comes in to the server as this object:
{ type, result }
Then I find the function name that matches the "type" property.
I (was) am using shorthand for objects (valid ES6).
As of about 5 minutes ago I thought of a more robust way to do this, incase you are sending bad messages:
[ func1, func2, func3, funcN ].filter(f => f.name === data.type).map(r => r())
The filter will return an empty array [], meaning no function was found.
If a function is found, it will return [ Function ], and execute it in .map().
It then sends back the result of the function to the client with the same function name as the type.
The client basically does the exact same thing!

Comments

Popular Posts