billstclair/elm-websocket-client/2.0.1

NOTE: the latest version is 4.1.0

WebSocketClient

Web sockets make it cheaper to talk to your servers.

Connecting to a server takes some time, so with web sockets, you make that connection once and then keep using. The major benefits of this are:

  1. It faster to send messages. No need to do a bunch of work for every single message.

  2. The server can push messages to you. With normal HTTP you would have to keep asking for changes, but a web socket, the server can talk to you whenever it wants. This means there is less unnecessary network traffic.

Web Sockets

Types

= PortVersion2

A custom type with one tag.

The tag encodes the version of the port JavaScript code. It changes every time that code changes incompatibly, to remind you that you need to update it, and change your open, openWithKey, and send calls accordingly.

type Config msg

Packages up your ports to put inside a State.

Opaque type, created by makeConfig.

type State msg

Internal state of the WebSocketClient module.

Create one with makeState, passed to most of the other functions.

type Response msg
= NoResponse
| CmdResponse (Cmd msg)
| ConnectedResponse
{ key : String
, description : String
}
| MessageReceivedResponse
{ key : String
, message : String
}
| ClosedResponse
{ key : String
, code : ClosedCode
, reason : String
, wasClean : Bool
, expected : Bool
}
| ErrorResponse Error

A response that your code must process to update your model.

NoResponse means there's nothing to do.

CmdResponse is a Cmd that you must return from your update function. It will send something out the sendPort in your Config.

ConnectedReponse tells you that an earlier call to send or keepAlive has successfully connected. You can usually ignore this.

MessageReceivedResponse is a message from one of the connected sockets.

ClosedResponse tells you that an earlier call to close has completed. Its code, reason, and wasClean fields are as passed by the JavaScript WebSocket interface. Its expected field will be True, if the response is to a close call on your part. It will be False if the close was unexpected, and reconnection attempts failed for 20 seconds (using exponential backoff between attempts).

ErrorResponse means that something went wrong. Details in the encapsulated Error.

type Error
= UnimplementedError { function : String }
| SocketAlreadyOpenError String
| SocketConnectingError String
| SocketClosingError String
| SocketNotOpenError String
| PortDecodeError { error : String }
| UnexpectedConnectedError
{ key : String
, description : String
}
| UnexpectedMessageError
{ key : String
, message : String
}
| LowLevelError
{ key : Maybe String
, code : String
, description : String
, name : Maybe String
}
| InvalidMessageError { json : String }

All the errors that can be returned in a Response.ErrorResponse.

If an error tag has a single String arg, that string is a socket key.

= NormalClosure
| GoingAwayClosure
| ProtocolErrorClosure
| UnsupportedDataClosure
| NoStatusRecvdClosure
| AbnormalClosure
| InvalidFramePayloadDataClosure
| PolicyViolationClosure
| MessageTooBigClosure
| MissingExtensionClosure
| InternalErrorClosure
| ServiceRestartClosure
| TryAgainLaterClosure
| BadGatewayClosure
| TLSHandshakeClosure
| TimedOutOnReconnect
| UnknownClosure

This will usually be NormalClosure. The rest are standard, except for UnknownClosure, which denotes a code that is not defined, and TimeoutOutOnReconnect, which means that exponential backoff connection reestablishment attempts timed out.

The standard codes are from https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent

State

makeConfig : (Value -> Cmd msg) -> Config msg

Make a real configuration, with your input and output ports.

The parameters are:

makeConfig sendPort

Where sendPort is your output (Cmd) port.

Your input (Sub) port should wrap a Json.Encode.Value with a message, and when your update function gets that message, it should pass it to process, and then store the returned State in your model, and handle the returned Response.

makeState : Config msg -> State msg

Make state to store in your model.

The Config arg is the result of makeConfig or makeSimulatorConfig.

getKeyUrl : String -> State msg -> Maybe String

Get the URL for a key.

getConfig : State msg -> Config msg

Get a State's Config

setConfig : Config msg -> State msg -> State msg

Set a State's Config.

Will likely break things if you do this while connections are active.

API

open : PortVersion -> State msg -> String -> ( State msg, Response msg )

Subscribe to any incoming messages on a websocket. You might say something like this:

type Msg = Echo String | ...


subscriptions model =
  open PortVersion2 "ws://echo.websocket.org" Echo

The first arg is a PortVersion, to remind you to update your JavaScript port code, when it changes incompatibly.

open PortVersion2 state url
keepAlive : State msg -> String -> ( State msg, Response msg )

Keep a connection alive, but do not report any messages. This is useful for keeping a connection open for when you only need to send messages. So you might say something like this:

let (state2, response) =
    keepAlive state "ws://echo.websocket.org"
in
    ...

Note: If the connection goes down, the effect manager tries to reconnect with an exponential backoff strategy. Any messages you try to send while the connection is down are queued and will be sent as soon as possible.

-> State msg
-> String
-> String
-> ( State msg, Response msg )

Send a message to a particular address. You might say something like this:

send PortVersion2 state "ws://echo.websocket.org" "Hello!"

You must call open or openWithKey before calling send.

If you call send before the connection has been established, or while it is being reestablished after it was lost, your message will be buffered and sent after the connection has been (re)established.

The first arg is a PortVersion, to remind you to update your JavaScript port code, if it changes incompatibly.

send PortVersion2 state key message
close : State msg -> String -> ( State msg, Response msg )

Close a WebSocket opened by open or keepAlive.

close state key

The key arg is either they key arg to openWithKey or keepAliveWithKey or the url arg to open or keepAlive.

process : State msg -> Value -> ( State msg, Response msg )

Process a Value that comes in over the subscription port.

-> State msg
-> String
-> String
-> ( State msg, Response msg )

Like open, but allows matching a unique key to the connection.

open uses the url as the key.

openWithKey PortVersion2 state key url
keepAliveWithKey : State msg -> String -> String -> ( State msg, Response msg )

Like keepAlive, but allows matching a unique key to the connection.

keeAliveWithKey state key url

Simulator

makeSimulatorConfig : (String -> Maybe String) -> Config msg

Make a Config that enables running your code in elm reactor.

The arg is a server simulator, which translates a message sent with send to a response.

Printing errors

errorToString : Error -> String

Convert an Error to a string, for simple reporting.

Turn a ClosedCode into a String, for debugging.