Phoenix JavaScript Client
The Phoenix JavaScript client provides real-time bidirectional communication capabilities for frontend applications interacting with Phoenix web framework backends. It leverages WebSockets and Phoenix Channels to enable features like chat, live notifications, and collaborative editing. The current stable version, 1.8.5, is released in conjunction with the Phoenix framework, leading to an irregular but consistent release cadence. A key differentiator is its robust channel-based publish/subscribe system, which is tightly integrated with the Elixir/Phoenix ecosystem, offering fault-tolerant and highly concurrent real-time services. It's designed to provide a structured approach to real-time communication, ensuring reliable message delivery and state management between client and server.
Common errors
-
WebSocket connection to 'ws://localhost:4000/socket' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
cause The Phoenix backend server is not running, the WebSocket URL is incorrect, or a firewall is blocking the connection to the specified port.fixStart your Phoenix server, verify the `socketUrl` points to the correct address and port, and check firewall settings to ensure the port is open. -
channel join 'topic' was refused
cause The server explicitly rejected the channel join request, commonly due to authentication failure, an invalid channel topic, or a server-side authorization policy preventing the join.fixExamine the `reason` payload from the `receive("error", ({ reason }) => ...)` callback for detailed error messages. Verify user authentication, the channel topic name, and review your Phoenix backend's `UserSocket` and `Channel` modules for authorization logic. -
channel join 'topic' timed out
cause The client did not receive an 'ok' or 'error' response from the server within the configured timeout period after attempting to join a channel. This might indicate network issues or an unresponsive server.fixCheck network connectivity between the client and the Phoenix server. Confirm the Phoenix server is running and not overloaded. The default join timeout can be adjusted in the `channel.join()` call if needed for slower networks.
Warnings
- breaking Upgrading the Phoenix framework from v1.1.x to v1.2.x may require adjustments to the JavaScript client and careful review of the framework's upgrade instructions. While the changelog primarily lists backend changes, tight coupling often means client-side updates are necessary for compatibility or to leverage new features.
- breaking Upgrading the Phoenix framework from v1.0.x to v1.1.x might introduce incompatibilities with older JavaScript client versions. Although the client-specific API changes are not always detailed in the framework's changelog, major framework updates often necessitate updating the client library and reviewing integration points.
- gotcha The Phoenix client uses WebSockets for real-time communication. Ensure your WebSocket URL (e.g., `ws://localhost:4000/socket`) is correct, and that your Phoenix backend server is running and configured to accept WebSocket connections on that path and port.
- gotcha Channel join requests can be refused by the server due to incorrect topic names, missing or invalid authentication tokens, or server-side authorization policies. Always handle the `receive("error")` callback from `channel.join()` to diagnose specific issues.
Install
-
npm install phoenix -
yarn add phoenix -
pnpm add phoenix
Imports
- Socket
import Socket from 'phoenix'; const { Socket } = require('phoenix');import { Socket } from 'phoenix' - Channel
import { Channel } from 'phoenix';const channel = socket.channel('topic', params); - LongPoll
import { LongPoll } from 'phoenix'
Quickstart
import { Socket } from "phoenix";
// Replace with your Phoenix server's WebSocket URL, e.g., 'ws://localhost:4000/socket'
const socketUrl = "ws://your-phoenix-app.com/socket";
const userToken = process.env.PHOENIX_AUTH_TOKEN ?? ''; // Use env var for auth or actual token
// Instantiate a new Socket connection
const socket = new Socket(socketUrl, { params: { userToken } });
// Connect to the socket
socket.connect();
socket.onOpen(() => console.log("Socket connected successfully!"));
socket.onError((error) => console.error("Socket error:", error));
socket.onClose(() => console.log("Socket closed."));
// Join a specific channel, e.g., 'room:lobby'
const channel = socket.channel("room:lobby", {});
// Set up event listeners for messages received on this channel
channel.on("new_msg", (payload) => {
console.log("Received new message:", payload.body);
});
channel.on("user_joined", (payload) => {
console.log("User joined channel:", payload.username);
});
// Attempt to join the channel and handle outcomes
channel.join()
.receive("ok", ({ messages }) => {
console.log("Joined channel successfully! Initial messages:", messages);
// Push a message to the channel after successful join
channel.push("new_msg", { body: "Hello Phoenix channel!" })
.receive("ok", (msg) => console.log("Message pushed successfully:", msg))
.receive("error", (reasons) => console.error("Failed to push message:", reasons))
.receive("timeout", () => console.warn("Message push timed out."));
})
.receive("error", ({ reason }) => {
console.error("Failed to join channel:", reason);
})
.receive("timeout", () => {
console.warn("Joining channel timed out. Server might be unreachable or slow.");
});
// Example of leaving a channel or disconnecting the socket after some time
// setTimeout(() => {
// channel.leave();
// socket.disconnect();
// console.log("Channel left and socket disconnected after 15 seconds.");
// }, 15000);