DEV Community

Avalander
Avalander

Posted on

9 2

Pixel Wars: Using Pusher in Elm

View the project on GitHub

Since I'm using Elm in my project, I needed to figure out how to use Pusher in Elm, because there is no Pusher client for it. Fortunately, Elm offers a very clean and nice way to interact with Javascript. I was positively surprised by how easy it actually was.

Using Pusher in Elm

Let's start with the code. Here's how I did it.

First, I declared two ports in an Elm module.

port module Pusher exposing (..)

port messages : (Pony -> msg) -> Sub msg

port connect : String -> Cmd msg
Enter fullscreen mode Exit fullscreen mode
  • messages will be invoked from Javascript every time the Pusher subscription receives a message. Nevermind the type Pony, that's going to change when I implement updating the game state in the backend.
  • connect will be invoked from Elm to create the Pusher connection. Javascript will listen to that message and open the connection.

Let's have a look at the Javascript code required to make this work.

import Elm from 'app/Main.elm'
import Pusher from 'pusher-js'

const mount_node = document.querySelector('#root')
const app = Elm.Main.embed(mount_node)
let pusher

app.ports.connect.subscribe(() => {
    pusher = new Pusher(PUSHER_KEY, {
        encrypted: true,
    })
    pusher.subscribe('ponies')
        .bind('pony-data', app.ports.messages.send)
})
Enter fullscreen mode Exit fullscreen mode

All functions prefixed with port in Elm are exposed in Javascript in the object app.ports. Therefore, I can call app.ports.connect.subscribe to run a callback in Javascript when the Pusher.connect command is executed in Elm. In a similar fashion, I can call app.ports.messages.send to invoke the function messages in Elm.

To glue everything in Elm, I need to subscribe to the function messages, and return the command connect in the update function when I want to connect to pusher. Here's how I did it in my Main.elm.

import Pusher

type Msg
    = OnPusherMessage Pony
    | OnFetchGame (WebData GameResponse)

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    case msg of
        OnPusherMessage pony ->
            ({ model | name = pony.name }, Cmd.none)
        OnFetchGame response ->
            (
                updateModel model response,
                Pusher.connect "connect"
            )

subscriptions : Model -> Sub Msg
subscriptions model =
    Pusher.messages OnPusherMessage
Enter fullscreen mode Exit fullscreen mode

There we go. Adding Pusher.messages in the subscriptions will trigger a OnPusherMessage with the received message every time app.ports.message.send is invoked in Javascript. Similarly, returning Pusher.connect in update will send an event to app.ports.connect when the client has received the game state, so that updates can start flowing.

Next Steps

The next step is to make the client send clicks to the server and have the server update the game state and send it back to all connected clients. Hopefully I'll have something functional enough to be deployed in a couple of days.

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (1)

Collapse
 
frosnerd profile image
Frank Rosner

Thank you so much for sharing this!

Image of AssemblyAI

Automatic Speech Recognition with AssemblyAI

Experience near-human accuracy, low-latency performance, and advanced Speech AI capabilities with AssemblyAI's Speech-to-Text API. Sign up today and get $50 in API credit. No credit card required.

Try the API

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay