Advanced Techniques with @briklab/slikr
Once comfortable with the basics, these patterns help you build robust real-time applications.
Custom Retry Strategies
ts
import slikr from "@briklab/slikr";
const client = slikr("wss://api.example.com");
// Exponential backoff with jitter
client.retryDelayIncreaseFn(current => {
const jitter = Math.random() * 0.1 * current; // Add up to 10% jitter
return current * 2 + jitter;
});
// Fibonacci backoff
let prev = 1000;
let curr = 1000;
client.retryDelayIncreaseFn(() => {
const next = prev + curr;
prev = curr;
curr = next;
return curr;
});Connection State Management
ts
import slikr from "@briklab/slikr";
class ConnectionManager {
private client: ReturnType<typeof slikr>;
private reconnectAttempts = 0;
private maxReconnects = 10;
constructor(url: string) {
this.client = slikr(url);
this.setupEventHandlers();
}
private setupEventHandlers() {
this.client.on("close", () => this.handleDisconnect());
this.client.on("open", () => {
console.log("Connected");
this.reconnectAttempts = 0;
});
}
private async handleDisconnect() {
if (this.reconnectAttempts >= this.maxReconnects) {
console.error("Max reconnection attempts reached");
return;
}
this.reconnectAttempts++;
const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
console.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
setTimeout(async () => {
try {
await this.client.connect();
} catch (error) {
console.error("Reconnection failed:", error.message);
}
}, delay);
}
async connect() {
await this.client.connect();
}
getClient() {
return this.client;
}
}Message Queuing and Offline Support
ts
import slikr from "@briklab/slikr";
class QueuedClient {
private client: ReturnType<typeof slikr>;
private queue: Array<{ event: string; data: any }> = [];
private connected = false;
constructor(url: string) {
this.client = slikr(url);
this.client.on("open", () => {
this.connected = true;
this.flushQueue();
});
this.client.on("close", () => {
this.connected = false;
});
}
async send(event: string, data: any) {
if (this.connected) {
await this.client.send(event, data);
} else {
this.queue.push({ event, data });
}
}
private async flushQueue() {
while (this.queue.length > 0) {
const message = this.queue.shift()!;
try {
await this.client.send(message.event, message.data);
} catch (error) {
console.error("Failed to send queued message:", error);
// Optionally re-queue or handle error
}
}
}
async connect() {
await this.client.connect();
}
}Binary Data Handling
ts
import slikr from "@briklab/slikr";
// Send large binary data with progress
async function sendLargeBinary(client: ReturnType<typeof slikr>, data: Uint8Array) {
const chunkSize = 16 * 1024; // 16KB chunks
const totalChunks = Math.ceil(data.length / chunkSize);
for (let i = 0; i < totalChunks; i++) {
const start = i * chunkSize;
const end = Math.min(start + chunkSize, data.length);
const chunk = data.slice(start, end);
await client.send("binary_chunk", {
index: i,
total: totalChunks,
data: chunk
});
// Report progress
console.log(`Sent chunk ${i + 1}/${totalChunks}`);
}
await client.send("binary_complete", { size: data.length });
}
// Receive and reassemble binary data
function receiveLargeBinary(client: ReturnType<typeof slikr>) {
const chunks: Uint8Array[] = [];
let expectedChunks = 0;
client.on("binary_chunk", (chunk) => {
chunks[chunk.index] = chunk.data;
console.log(`Received chunk ${chunk.index + 1}/${chunk.total}`);
if (chunks.length === chunk.total) {
// All chunks received, reassemble
const totalSize = chunks.reduce((sum, c) => sum + c.length, 0);
const result = new Uint8Array(totalSize);
let offset = 0;
for (const c of chunks) {
result.set(c, offset);
offset += c.length;
}
console.log("Binary data reassembled, size:", totalSize);
}
});
}Transport-Specific Features
ts
import slikr from "@briklab/slikr";
const client = slikr("https://example.com/wt"); // WebTransport URL
// Check transport type
console.log("Using transport:", client.status.type);
// WebTransport-specific features (when available)
if (client.status.type === "WebTransport") {
// WebTransport supports datagrams for unreliable delivery
// slikr handles this automatically, but you can check status
}
// WebSocket fallback features
if (client.status.type === "WebSocket") {
// WebSocket provides reliable ordered delivery
}Performance Optimization
ts
import slikr from "@briklab/slikr";
const client = slikr("wss://high-throughput.example.com")
// Minimize keepalive for high-frequency apps
.keepalive(true)
.keepalive(30000) // 30s intervals
// Aggressive retry for critical connections
.retry(10)
.retryDelay(500)
.retryTimeout(2000);
// Batch messages to reduce overhead
class MessageBatcher {
private messages: Array<{ event: string; data: any }> = [];
private batchSize = 10;
private flushInterval = 100; // ms
constructor(private client: ReturnType<typeof slikr>) {
setInterval(() => this.flush(), this.flushInterval);
}
add(event: string, data: any) {
this.messages.push({ event, data });
if (this.messages.length >= this.batchSize) {
this.flush();
}
}
private async flush() {
if (this.messages.length === 0) return;
const batch = [...this.messages];
this.messages = [];
await this.client.send("batch", batch);
}
}Error Recovery Patterns
ts
import slikr from "@briklab/slikr";
import { Slikr } from "@briklab/slikr";
class ResilientClient {
private client: ReturnType<typeof slikr>;
private reconnectTimer?: NodeJS.Timeout;
constructor(url: string) {
this.client = slikr(url)
.retry(3)
.totalTimeout(10000)
.onTotalTimeout(() => this.scheduleReconnect());
}
private scheduleReconnect() {
if (this.reconnectTimer) return;
this.reconnectTimer = setTimeout(async () => {
this.reconnectTimer = undefined;
try {
await this.client.connect();
console.log("Reconnected successfully");
} catch (error) {
console.error("Reconnection failed, will retry later");
this.scheduleReconnect(); // Exponential backoff could be added here
}
}, 5000);
}
async connect() {
try {
await this.client.connect();
} catch (error) {
if (error instanceof Slikr.Error) {
console.error("Connection failed:", error.message);
this.scheduleReconnect();
}
throw error;
}
}
}Live Demo
Console
No logs yet.
