### phoenix

`1.8.7`
Need help reading this?

### phoenix

Phoenix Channels JavaScript client

## Socket Connection

A single connection is established to the server and channels are multiplexed over the connection. Connect to the server using the `Socket` class:

The `Socket` constructor takes the mount point of the socket, the authentication params, as well as options that can be found in the Socket docs, such as configuring the `LongPoll` transport, and heartbeat.

## Channels

Channels are isolated, concurrent processes on the server that subscribe to topics and broker events between the client and server. To join a channel, you must provide the topic, and channel params for authorization. Here's an example chat room example where `"new_msg"` events are listened for, messages are pushed to the server, and the channel is joined with ok/error/timeout matches:

    let channel = socket.channel("room:123", {token: roomToken})
    channel.on("new_msg", msg => console.log("Got message", msg) )
    $input.onEnter( e => {
      channel.push("new_msg", {body: e.target.val}, 10000)
        .receive("ok", (msg) => console.log("created message", msg) )
        .receive("error", (reasons) => console.log("create failed", reasons) )
        .receive("timeout", () => console.log("Networking issue...") )
    })

    channel.join()
      .receive("ok", ({messages}) => console.log("catching up", messages) )
      .receive("error", ({reason}) => console.log("failed join", reason) )
      .receive("timeout", () => console.log("Networking issue. Still waiting..."))

## Joining

Creating a channel with `socket.channel(topic, params)`, binds the params to `channel.params`, which are sent up on `channel.join()`. Subsequent rejoins will send up the modified params for updating authorization params, or passing up last_message_id information. Successful joins receive an "ok" status, while unsuccessful joins receive "error".

With the default serializers and WebSocket transport, JSON text frames are used for pushing a JSON object literal. If an `ArrayBuffer` instance is provided, binary encoding will be used and the message will be sent with the binary opcode.

Note: binary messages are only supported on the WebSocket transport.

## Duplicate Join Subscriptions

While the client may join any number of topics on any number of channels, the client may only hold a single subscription for each unique topic at any given time. When attempting to create a duplicate subscription, the server will close the existing channel, log a warning, and spawn a new channel for the topic. The client will have their `channel.onClose` callbacks fired for the existing channel, and the new channel join will have its receive hooks processed as normal.

## Pushing Messages

From the previous example, we can see that pushing messages to the server can be done with `channel.push(eventName, payload)` and we can optionally receive responses from the push. Additionally, we can use `receive("timeout", callback)` to abort waiting for our other `receive` hooks and take action after some period of waiting. The default timeout is 10000ms.

## Socket Hooks

Lifecycle events of the multiplexed connection can be hooked into via `socket.onError()` and `socket.onClose()` events, ie:

    socket.onError( () => console.log("there was an error with the connection!") )
    socket.onClose( () => console.log("the connection dropped") )

## Channel Hooks

For each joined channel, you can bind to `onError` and `onClose` events to monitor the channel lifecycle, ie:

    channel.onError( () => console.log("there was an error!") )
    channel.onClose( () => console.log("the channel has gone away gracefully") )

### onError hooks

`onError` hooks are invoked if the socket connection drops, or the channel crashes on the server. In either case, a channel rejoin is attempted automatically in an exponential backoff manner.

### onClose hooks

`onClose` hooks are invoked only in two cases. 1) the channel explicitly closed on the server, or 2). The client explicitly closed, by calling `channel.leave()`

## Presence

The `Presence` object provides features for syncing presence information from the server with the client and handling presences joining and leaving.

### Syncing state from the server

To sync presence state from the server, first instantiate an object and pass your channel in to track lifecycle events:

    let channel = socket.channel("some:topic")
    let presence = new Presence(channel)

Next, use the `presence.onSync` callback to react to state changes from the server. For example, to render the list of users every time the list changes, you could write:

    presence.onSync(() => {
      myRenderUsersFunction(presence.list())
    })

### Listing Presences

`presence.list` is used to return a list of presence information based on the local state of metadata. By default, all presence metadata is returned, but a `listBy` function can be supplied to allow the client to select which metadata to use for a given presence. For example, you may have a user online from different devices with a metadata status of "online", but they have set themselves to "away" on another device. In this case, the app may choose to use the "away" status for what appears on the UI. The example below defines a `listBy` function which prioritizes the first metadata which was registered for each user. This could be the first tab they opened, or the first device they came online from:

    let listBy = (id, {metas: [first, ...rest]}) => {
      first.count = rest.length + 1 // count of this user's presences
      first.id = id
      return first
    }
    let onlineUsers = presence.list(listBy)

### Handling individual presence join and leave events

The `presence.onJoin` and `presence.onLeave` callbacks can be used to react to individual presences joining and leaving the app. For example:

    let presence = new Presence(channel)

    // detect if user has joined for the 1st time or from another tab/device
    presence.onJoin((id, current, newPres) => {
      if(!current){
        console.log("user has entered for the first time", newPres)
      } else {
        console.log("user additional presence", newPres)
      }
    })

    // detect if user has left from all tabs/devices, or is still present
    presence.onLeave((id, current, leftPres) => {
      if(current.metas.length === 0){
        console.log("user has left from all devices", leftPres)
      } else {
        console.log("user left from a device", leftPres)
      }
    })
    // receive presence data from server
    presence.onSync(() => {
      displayUsers(presence.list())
    })

phoenix

### Channel

new Channel(topic: string, params: (Object | function), socket: Socket)
Parameters
topic `(string)`
params `((Object | function))`
socket `(Socket)`
Instance Members
▸ join(timeout)

Join the channel

join(timeout: integer): Push
Parameters
timeout `(integer = `this.timeout`)`
Returns
`Push`:
▸ onClose(callback)

Hook into channel close

onClose(callback: Function)
Parameters
callback `(Function)`
▸ onError(callback)

Hook into channel errors

onError(callback: Function)
Parameters
callback `(Function)`
▸ on(event, callback)

Subscribes on channel events

Subscription returns a ref counter, which can be used later to unsubscribe the exact event listener

on(event: string, callback: Function): integer
Parameters
event `(string)`
callback `(Function)`
Returns
`integer`: ref
Example

    const ref1 = channel.on("event", do_stuff)
    const ref2 = channel.on("event", do_other_stuff)
    channel.off("event", ref1)
    // Since unsubscription, do_stuff won't fire,
    // while do_other_stuff will keep firing on the "event"

▸ off(event, ref)

Unsubscribes off of channel events

Use the ref returned from a channel.on() to unsubscribe one handler, or pass nothing for the ref to unsubscribe all handlers for the given event.

off(event: string, ref: integer)
Parameters
event `(string)`
ref `(integer)`
Example

    // Unsubscribe the do_stuff handler
    const ref1 = channel.on("event", do_stuff)
    channel.off("event", ref1)

    // Unsubscribe all handlers from event
    channel.off("event")

▸ push(event, payload, timeout = this.timeout)

Sends a message `event` to phoenix with the payload `payload`. Phoenix receives this in the `handle_in(event, payload, socket)` function. if phoenix replies or it times out (default 10000ms), then optionally the reply can be received.

push(event: string, payload: Object, timeout: number?): Push
Parameters
event `(string)`
payload `(Object)`
timeout `(number? = `this.timeout`)`
Returns
`Push`:
Example

    channel.push("event")
      .receive("ok", payload => console.log("phoenix replied:", payload))
      .receive("error", err => console.log("phoenix errored", err))
      .receive("timeout", () => console.log("timed out pushing"))

▸ leave(timeout)

Leaves the channel

Unsubscribes from server events, and instructs channel to terminate on server

Triggers onClose() hooks

To receive leave acknowledgements, use the `receive` hook to bind to the server ack, ie:

leave(timeout: integer): Push
Parameters
timeout `(integer = `this.timeout`)`
Returns
`Push`:
Example

    channel.leave().receive("ok", () => alert("left!") )

▸ onMessage(_event, payload, _ref, event, ref)

Overridable message hook

Receives all events for specialized message handling before dispatching to the channel callbacks.

Must return the payload, modified or unmodified

onMessage(_event: any, payload: Object, _ref: any, event: string, ref: integer): Object
Parameters
_event `(any)`
payload `(Object)`
_ref `(any)`
event `(string)`
ref `(integer)`
Returns
`Object`:

### Push

Initializes the Push

new Push(channel: Channel, event: string, payload: Object, timeout: number)
Parameters
channel `(Channel)` The Channel
event `(string)` The event, for example `"phx_join"`
payload `(Object)` The payload, for example `{user_id: 123}`
timeout `(number)` The push timeout in milliseconds
Instance Members
▸ resend(timeout)
resend(timeout: number)
Parameters
timeout `(number)`
▸ send()
send()
▸ receive(status, callback)
receive(status: any, callback: any)
Parameters
status `(any)`
callback `(any)`

### Timer

Creates a timer that accepts a `timerCalc` function to perform calculated timeout retries, such as exponential backoff.

new Timer(callback: Function, timerCalc: Function)
Parameters
callback `(Function)`
timerCalc `(Function)`
Example

    let reconnectTimer = new Timer(() => this.connect(), function(tries){
      return [1000, 5000, 10000][tries - 1] || 10000
    })
    reconnectTimer.scheduleTimeout() // fires after 1000
    reconnectTimer.scheduleTimeout() // fires after 5000
    reconnectTimer.reset()
    reconnectTimer.scheduleTimeout() // fires after 1000

Instance Members
▸ scheduleTimeout()

Cancels any previous scheduleTimeout and schedules callback

scheduleTimeout()

### Presence

Initializes the Presence

new Presence(channel: Channel, opts: Object)
Parameters
channel `(Channel)` The Channel
opts `(Object = `{}`)` The options, for example `{events: {state: "state", diff: "diff"}}`
Static Members
▸ syncState(currentState, newState, onJoin, onLeave)

Used to sync the list of presences on the server with the client's state. An optional `onJoin` and `onLeave` callback can be provided to react to changes in the client's local presences across disconnects and reconnects with the server.

syncState(currentState: any, newState: any, onJoin: any, onLeave: any): Presence
Parameters
currentState `(any)`
newState `(any)`
onJoin `(any)`
onLeave `(any)`
Returns
`Presence`:
▸ syncDiff(state, diff, onJoin, onLeave)

Used to sync a diff of presence join and leave events from the server, as they happen. Like `syncState`, `syncDiff` accepts optional `onJoin` and `onLeave` callbacks to react to a user joining or leaving from a device.

syncDiff(state: any, diff: any, onJoin: any, onLeave: any): Presence
Parameters
state `(any)`
diff `(any)`
onJoin `(any)`
onLeave `(any)`
Returns
`Presence`:
▸ list(presences, chooser)

Returns the array of presences, with selected metadata.

list(presences: Object, chooser: Function): Presence
Parameters
presences `(Object)`
chooser `(Function)`
Returns
`Presence`:

### Socket

Initializes the Socket *

For IE8 support use an ES5-shim (https://github.com/es-shims/es5-shim)

new Socket(endPoint: string, opts: Object?)
Parameters
endPoint `(string)` The string WebSocket endpoint, ie, `"ws://example.com/socket"` , `"wss://example.com"` `"/socket"` (inherited host & protocol)
opts `(Object? = `{}`)` Optional configuration

Name | Description
--- | ---
opts.transport `Function?` | The Websocket Transport, for example WebSocket or Phoenix.LongPoll. Defaults to WebSocket with automatic LongPoll fallback if WebSocket is not defined. To fallback to LongPoll when WebSocket attempts fail, use `longPollFallbackMs: 2500`.
opts.longPollFallbackMs `number?` | The millisecond time to attempt the primary transport before falling back to the LongPoll transport. Disabled by default.
opts.debug `boolean?` | When true, enables debug logging. Default false.
opts.encode `Function?` | The function to encode outgoing messages. Defaults to JSON encoder.
opts.decode `Function?` | The function to decode incoming messages. Defaults to JSON:
opts.timeout `number?` | The default timeout in milliseconds to trigger push timeouts. Defaults `DEFAULT_TIMEOUT`
opts.heartbeatIntervalMs `number?` | The millisec interval to send a heartbeat message
opts.reconnectAfterMs `Function?` | The optional function that returns the socket reconnect interval, in milliseconds. Defaults to stepped backoff of:
opts.rejoinAfterMs `Function?` | The optional function that returns the millisec rejoin interval for individual channels.
opts.logger `Function?` | The optional function for specialized logging, ie:
opts.longpollerTimeout `number?` | The maximum timeout of a long poll AJAX request. Defaults to 20s (double the server long poll timer).
opts.params `(Object | function)?` | The optional params to pass when connecting
opts.authToken `string?` | the optional authentication token to be exposed on the server under the `:auth_token` connect_info key.
opts.binaryType `string?` | The binary type to use for binary WebSocket frames. Defaults to "arraybuffer"
opts.vsn `vsn?` | The serializer's protocol version to send on connect. Defaults to DEFAULT_VSN.
opts.sessionStorage `Object?` | An optional Storage compatible object Phoenix uses sessionStorage for longpoll fallback history. Overriding the store is useful when Phoenix won't have access to `sessionStorage` . For example, This could happen if a site loads a cross-domain channel in an iframe. Example usage:
    class InMemoryStorage {
      constructor() { this.storage = {} }
      getItem(keyName) { return this.storage[keyName] || null }
      removeItem(keyName) { delete this.storage[keyName] }
      setItem(keyName, keyValue) { this.storage[keyName] = keyValue }
    }

Instance Members
▸ getLongPollTransport()

Returns the LongPoll transport reference

getLongPollTransport()
▸ replaceTransport(newTransport)

Disconnects and replaces the active transport

replaceTransport(newTransport: Function)
Parameters
newTransport `(Function)` The new transport class to instantiate
▸ protocol()

Returns the socket protocol

protocol(): string
Returns
`string`:
▸ endPointURL()

The fully qualified socket url

endPointURL(): string
Returns
`string`:
▸ disconnect(callback, code, reason)

Disconnects the socket

See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes for valid status codes.

disconnect(callback: Function, code: integer, reason: string)
Parameters
callback `(Function)` Optional callback which is called after socket is disconnected.
code `(integer)` A status code for disconnection (Optional).
reason `(string)` A textual description of the reason to disconnect. (Optional)
▸ connect(params)
connect(params: Object)
Parameters
params `(Object)` The params to send when connecting, for example `{user_id: userToken}`

Passing params to connect is deprecated; pass them in the Socket constructor instead: `new Socket("/socket", {params: {user_id: userToken}})`.

▸ log(kind, msg, data)

Logs the message. Override `this.logger` for specialized logging. noops by default

log(kind: string, msg: string, data: Object)
Parameters
kind `(string)`
msg `(string)`
data `(Object)`
▸ hasLogger()

Returns true if a logger has been set on this socket.

hasLogger()
▸ onOpen(callback)

Registers callbacks for connection open events

onOpen(callback: Function)
Parameters
callback `(Function)`
Example

    socket.onOpen(function(){ console.info("the socket was opened") })

▸ onClose(callback)

Registers callbacks for connection close events

onClose(callback: Function)
Parameters
callback `(Function)`
▸ onError(callback)

Registers callbacks for connection error events

onError(callback: Function)
Parameters
callback `(Function)`
Example

    socket.onError(function(error){ alert("An error occurred") })

▸ onMessage(callback)

Registers callbacks for connection message events

onMessage(callback: Function)
Parameters
callback `(Function)`
▸ ping(callback)

Pings the server and invokes the callback with the RTT in milliseconds

ping(callback: Function)
Parameters
callback `(Function)` Returns true if the ping was pushed or false if unable to be pushed.
▸ connectionState()
connectionState(): string
Returns
`string`:
▸ isConnected()
isConnected(): boolean
Returns
`boolean`:
▸ off(refs, null-null)

Removes `onOpen`, `onClose`, `onError,` and `onMessage` registrations.

off(refs: any, null-null: refs)
Parameters
refs `(any)`
null-null `(refs)` list of refs returned by calls to `onOpen` , `onClose` , `onError,` and `onMessage`
▸ channel(topic, chanParams)

Initiates a new channel for the given topic

channel(topic: string, chanParams: Object): Channel
Parameters
topic `(string)`
chanParams `(Object = `{}`)` Parameters for the channel
Returns
`Channel`:
▸ push(data)
push(data: Object)
Parameters
data `(Object)`
▸ makeRef()

Return the next message ref, accounting for overflows

makeRef(): string
Returns
`string`: