Channels
Channel Basics
Channels are isolated message streams that allow you to group related real-time communication. Each channel operates independently, so messages sent to one channel won't be received by clients connected to other channels.
ts
// Different channels are completely isolated
const chatSocket = new IttySocket('chat-room-1')
const gameSocket = new IttySocket('game-room-5')
const docSocket = new IttySocket('document-abc123')
Channel Naming
Naming Conventions
- Use descriptive, unique names
- Include relevant identifiers (room IDs, user IDs, etc.)
- Keep names URL-safe (no spaces or special characters)
ts
// Good channel names
new IttySocket('chat-general')
new IttySocket('game-room-123')
new IttySocket('document-editing-456')
new IttySocket('user-notifications-789')
// Avoid these patterns
new IttySocket('chat room') // spaces
new IttySocket('room#123') // special characters
Dynamic Channel Names
ts
// Based on room/session IDs
const roomId = 'abc123'
const socket = new IttySocket(`chat-${roomId}`)
// Based on user interactions
const documentId = getCurrentDocumentId()
const collabSocket = new IttySocket(`document-${documentId}`)
// Hierarchical naming
const socket = new IttySocket(`team-${teamId}-project-${projectId}`)
Channel Privacy
Public Channels (Demo Mode)
Using the demo API key allows anyone to join any channel. This is perfect for:
- Prototyping and development
- Public chat rooms
- Open collaboration spaces
- Non-sensitive real-time features
ts
// Anyone can join this channel
const publicSocket = new IttySocket('public-chat')
// or explicitly with demo key
const publicSocket = new IttySocket('public-chat', { apiKey: 'demo' })
Private Channels (API Key Required)
With your own API key, channels become private to your application:
- Only your application can create/join channels
- Secure for sensitive data
- Production-ready
ts
const privateSocket = new IttySocket('private-room-123', {
apiKey: 'your-secret-api-key'
})
Channel Management
Multiple Channels per Client
A single client can connect to multiple channels simultaneously:
ts
class MultiChannelClient {
constructor(userId) {
this.userId = userId
this.channels = new Map()
}
joinChannel(channelName) {
if (this.channels.has(channelName)) return
const socket = new IttySocket(channelName, {
apiKey: 'your-api-key'
})
// Add common message handling
socket.subscribe('user-message', this.handleMessage.bind(this))
socket.subscribe('system-notification', this.handleNotification.bind(this))
this.channels.set(channelName, socket)
return socket
}
leaveChannel(channelName) {
const socket = this.channels.get(channelName)
if (socket) {
socket.close()
this.channels.delete(channelName)
}
}
sendToChannel(channelName, type, data) {
const socket = this.channels.get(channelName)
if (socket) {
socket.send(type, { ...data, userId: this.userId })
}
}
}
Channel Discovery
For applications that need dynamic channel discovery:
ts
// Use a main lobby channel to coordinate
const lobbySocket = new IttySocket('lobby')
// Announce available rooms
lobbySocket.send('room-created', {
roomId: 'game-123',
roomName: 'Epic Battle Arena',
playerCount: 2,
maxPlayers: 4
})
// Listen for room announcements
lobbySocket.subscribe('room-created', ({ roomId, roomName, playerCount, maxPlayers }) => {
addRoomToList(roomId, roomName, playerCount, maxPlayers)
})
// Join a specific room
function joinRoom(roomId) {
const gameSocket = new IttySocket(`game-${roomId}`)
// Announce join in lobby
lobbySocket.send('player-joined-room', {
roomId,
playerId: getCurrentUserId()
})
return gameSocket
}
Channel Lifecycle
Connection Management
ts
class ChannelManager {
constructor() {
this.activeChannels = new Map()
}
async connect(channelName, options = {}) {
// Prevent duplicate connections
if (this.activeChannels.has(channelName)) {
return this.activeChannels.get(channelName)
}
const socket = new IttySocket(channelName, options)
// Add connection monitoring
socket.ws.addEventListener('open', () => {
console.log(`Connected to channel: ${channelName}`)
this.onChannelConnected(channelName)
})
socket.ws.addEventListener('close', () => {
console.log(`Disconnected from channel: ${channelName}`)
this.activeChannels.delete(channelName)
this.onChannelDisconnected(channelName)
})
this.activeChannels.set(channelName, socket)
return socket
}
disconnect(channelName) {
const socket = this.activeChannels.get(channelName)
if (socket) {
socket.close()
this.activeChannels.delete(channelName)
}
}
disconnectAll() {
for (const [channelName, socket] of this.activeChannels) {
socket.close()
}
this.activeChannels.clear()
}
onChannelConnected(channelName) {
// Handle successful connection
}
onChannelDisconnected(channelName) {
// Handle disconnection, maybe attempt reconnect
}
}
Cleanup and Resource Management
ts
// Automatic cleanup on page unload
window.addEventListener('beforeunload', () => {
// Notify other users you're leaving
activeChannels.forEach((socket, channelName) => {
socket.send('user-leaving', {
userId: getCurrentUserId(),
timestamp: Date.now()
})
socket.close()
})
})
// Memory leak prevention
class SmartSocket {
constructor(channelName, options) {
this.socket = new IttySocket(channelName, options)
this.listeners = new Set()
}
subscribe(type, handler) {
const unsubscribe = this.socket.subscribe(type, handler)
this.listeners.add(unsubscribe)
// Return enhanced unsubscribe
return () => {
unsubscribe()
this.listeners.delete(unsubscribe)
}
}
close() {
// Clean up all listeners
this.listeners.forEach(unsubscribe => unsubscribe())
this.listeners.clear()
this.socket.close()
}
}
Best Practices
Channel Naming Strategy
ts
// Use consistent naming patterns
const CHANNEL_PATTERNS = {
chat: (roomId) => `chat-${roomId}`,
game: (gameId) => `game-${gameId}`,
document: (docId) => `doc-${docId}`,
notification: (userId) => `notify-${userId}`,
presence: (teamId) => `presence-${teamId}`
}
// Usage
const chatSocket = new IttySocket(CHANNEL_PATTERNS.chat('room123'))
const gameSocket = new IttySocket(CHANNEL_PATTERNS.game('battle456'))
Performance Considerations
- Limit the number of simultaneous channels per client
- Use channel hierarchy to reduce message volume
- Implement message throttling for high-frequency events
- Clean up unused channels promptly
Security Notes
- Never put sensitive data in channel names (they may be logged)
- Use your own API key for production applications
- Implement proper authentication before allowing channel access
- Consider message encryption for sensitive real-time data