Client: Channels
Subscribe to real-time messages published by the server to named channels. Supports optional history on initial join.
Subscribing to a channel
const { , } = await .(
"news:global",
() => {
.("Live message:", );
}
);
if (!) {
.("Subscription failed (guarded?)");
}
The first argument is the channel name. The second is a callback for incoming messages.
With message history
You can optionally request recent messages when subscribing:
const { , } = await .(
"events:dashboard",
() => {
.("Live update:", );
},
{ : 5 }
);
.(() => {
const = .();
renderHistoricalEvent();
});
History is only available if the server explicitly stores it: writeChannel(, , historyLimit)
.
With message history since a specific point
If persistence is enabled for a channel, you can request messages since a specific timestamp or message ID:
// Get messages since a specific timestamp (milliseconds since epoch)
const { , } = await .(
"events:dashboard",
() => {
.("Live update:", );
},
{
: 100,
: 1682450400000,
}
);
// Or get messages since a specific message ID
const { , } = await .(
"events:dashboard",
() => {
.("Live update:", );
},
{
: 100,
: "message-id-123",
}
);
The since
parameter requires persistence to be enabled for the channel on
the server using enableChannelPersistence()
.
Retrieving channel history without subscribing
You can retrieve historical messages from a channel without subscribing to it:
// Get the most recent messages
const { , } = await .(
"events:dashboard",
{
: 50,
}
);
// Get messages since a specific timestamp
const { , } = await .(
"events:dashboard",
{
: 50,
: 1682450400000,
}
);
// Get messages since a specific message ID
const { , } = await .(
"events:dashboard",
{
: 50,
: "message-id-123",
}
);
// Process the historical messages
.(() => {
const = .();
renderHistoricalEvent();
});
Unsubscribing
To stop receiving updates:
await .("news:global");
Message format
Channel messages are always sent as raw strings.
If your server publishes structured data (e.g. JSON.stringify(...)
), you must parse it yourself:
.("alerts", () => {
try {
const = .();
switch (.type) {
case "alert":
showAlert(.message);
break;
case "announcement":
renderBanner(.content);
break;
default:
.("Unknown message type:", );
}
} catch () {
.("Failed to parse channel message:", );
}
});
Use cases
- Notifications
- Alerts, banners, user-specific pushes
- Live dashboards
- Server stats, performance metrics, monitoring feeds
- Broadcasting
- Build logs, event updates, task progress
- Chat applications
- Message history, pagination, catching up on missed messages
- Activity feeds
- Loading historical activities and receiving real-time updates
For presence indicators, typing status, and ephemeral per-user state, use presence instead.
Best practices
- Unsubscribe when done
- Frees resources and avoids duplicate subscriptions
- Parse carefully
- Messages are strings: use
try/catch
when parsing JSON
- Messages are strings: use
- Resubscribe on reconnect
- Keep a list of active channels and restore them after connection loss
- Use pagination for large history
- For channels with extensive history, use
getChannelHistory
with thesince
parameter to implement pagination
- For channels with extensive history, use
- Consider timestamp format
- When using
since
with a timestamp, use milliseconds since epoch (e.g.,Date.now()
)
- When using
- Error handling
- Always check the
success
flag when retrieving history, as persistence might not be enabled for all channels
- Always check the