Skip to content

WebSocket (client)

WebSocketActor opens a client-side WebSocket connection to a remote endpoint. For accepting incoming WS connections (server side), see ServerWebSocketActor.

import { ActorSystem, Props, WebSocketActor } from 'actor-ts';
const ws = system.actorOf(
Props.create(() => new WebSocketActor({
url: 'wss://realtime.example.com/feed',
protocols: ['my-proto-v1'],
headers: {
authorization: `Bearer ${process.env.API_TOKEN}`,
},
})),
'ws-client',
);
// Subscribe to inbound messages:
ws.tell({ kind: 'subscribe', subscriber: feedHandler });
// Send:
ws.tell({ kind: 'send', payload: JSON.stringify({ subscribe: 'channel-1' }) });
interface WebSocketActorSettings extends BrokerCommonSettings {
url: string; // ws:// or wss://
protocols?: string | string[]; // subprotocols
headers?: Record<string, string>; // initial-handshake headers
pingIntervalMs?: number; // application-level ping; default off
}
class FeedHandler extends Actor<WsInbound> {
override onReceive(msg: WsInbound): void {
if (msg.kind === 'text') {
const event = JSON.parse(msg.payload);
this.handleEvent(event);
} else if (msg.kind === 'binary') {
// raw Uint8Array
this.handleBinary(msg.payload);
}
}
}

Two inbound kinds — text and binary — matching the WebSocket frame types. The framework doesn’t dispatch on payload content; that’s up to the subscriber.

The base BrokerActor lifecycle handles reconnect with backoff. An unexpected disconnect:

  • Transitions the actor to disconnected.
  • Fires BrokerDisconnected on the event stream.
  • Starts the reconnect cycle.
  • After each successful re-connect, fires BrokerConnected.

Outbound messages sent during disconnection are buffered (per the outbound buffer policy). Inbound subscribers are preserved across reconnect.

new WebSocketActor({
url: 'wss://...',
pingIntervalMs: 30_000, // send a ping every 30s
});

Application-level ping prevents intermediate proxies / load balancers from closing idle connections. Most production WebSocket setups need this.

The protocol-level WebSocket ping (control frame) is sent automatically; the application-level ping is for proxies that inspect payload, not frames.

Three primary fits:

  1. Subscribing to real-time data feeds — stock tickers, crypto exchanges, social-media streams.
  2. Outbound WebSocket clients to third-party services (Slack RTM, OpenAI streaming, IoT vendor APIs).
  3. Custom WS-based protocols layered on top.

For server-side WebSocket (accepting client connections), use ServerWebSocketActor.