Loading article...
When building modern web apps, logging user behavior or system events reliably is essential. However, network conditions are unpredictableโso sending analytics events must be delayed, serialized, and resilient to transient failures.
Let's build an SDK that:
logEvent()Analytics sent event 1
Analytics sent event 2
...
-----------------------
Failed to send event 5
Retrying sending event 5
-----------------------
Analytics sent event 5
...
class SDK { constructor() { this.queue = []; this.isSending = false; this.sendCount = 0; } // Enqueue an event for later processing logEvent(event) { this.queue.push(event); console.log(`Logged event: ${event}`); return this; } // Sleep utility for delays sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // Attempt to send a single event, with retry on failure async sendEventWithRetry(event) { await this.sleep(1000); // Initial send delay if (this.sendCount % 5 === 0) { // Simulated failure console.log('-----------------------'); console.log(`Failed to send ${event}`); console.log(`Retrying sending ${event}`); console.log('-----------------------'); await this.sleep(1000); // Retry delay } console.log(`Analytics sent ${event}`); } // Process the queue serially async send() { if (this.isSending || this.queue.length === 0) return; this.isSending = true; while (this.queue.length > 0) { const event = this.queue.shift(); this.sendCount++; await this.sendEventWithRetry(event); } this.isSending = false; } } // ------------------------- // ๐งช Usage Example // ------------------------- const runExample = async () => { const sdk = new SDK(); // Log 10 events for (let i = 1; i <= 10; i++) { sdk.logEvent(`event ${i}`); } // Start sending await sdk.send(); }; runExample();
Every call to logEvent() pushes the event into an internal array.
The send() method ensures:
this.isSending)this.queue.shift())Every 5th event (sendCount % 5 === 0) fails, logs a failure, waits another second, and retries sending.
The logic does not proceed to the next event until the current one (including its retry) completes.
sleep() is abstracted for clarity.Test your understanding with 3 quick questions