UNPKG

ttf-api

Version:

The TrueToForm API SDK

114 lines (99 loc) 3.09 kB
class EventQueue { constructor(client) { if (EventQueue.instance) { return EventQueue.instance; } this.eventQueue = []; this.MAX_BATCH_SIZE = 50; this.MAX_TIME_INTERVAL = 5000; this.sendEventsTimer = null; this.client = client; this.loadQueueFromLocalStorage(); // Send remaining events on page unload window.addEventListener("beforeunload", () => { this.sendEvents(); }); // Handle storage events to synchronize across tabs window.addEventListener("storage", (event) => { if (event.key === "analyticsEventQueue") { this.loadQueueFromLocalStorage(); } }); EventQueue.instance = this; } static getInstance(client) { if (!EventQueue.instance) { EventQueue.instance = new EventQueue(client); } return EventQueue.instance; } loadQueueFromLocalStorage() { try { const storedQueue = localStorage.getItem("analyticsEventQueue"); if (storedQueue) { this.eventQueue = JSON.parse(storedQueue); } } catch (error) { console.error("Failed to load event queue from localStorage:", error); } } saveQueueToLocalStorage() { try { localStorage.setItem( "analyticsEventQueue", JSON.stringify(this.eventQueue) ); } catch (error) { console.error("Failed to save event queue to localStorage:", error); } } enqueueEvent(event) { // save the latest widget state if provided // and pass it to the next event if it doesn't have one const widgetState = event.metadata.widgetState; if (widgetState) { // make sure it's object and not empty if (typeof widgetState === "object" && Object.keys(widgetState).length) { this.latestWidgetState = widgetState; } } // if the event already has a widget state, we are setting // the event's widget state to it again. while if it doesn't // then this event will have the latest widget state from the previous event if (this.latestWidgetState) { event.metadata.widgetState = this.latestWidgetState; } this.eventQueue.push(event); this.saveQueueToLocalStorage(); this.checkAndSendEvents(); } checkAndSendEvents() { if (this.eventQueue.length >= this.MAX_BATCH_SIZE) { this.sendEvents(); } else if (!this.sendEventsTimer) { this.sendEventsTimer = setTimeout(() => { this.sendEvents(); }, this.MAX_TIME_INTERVAL); } } async sendEvents() { if (this.sendEventsTimer) { clearTimeout(this.sendEventsTimer); this.sendEventsTimer = null; } if (this.eventQueue.length === 0) return; const eventsToSend = [...this.eventQueue]; this.eventQueue = []; this.saveQueueToLocalStorage(); try { await this.client.post("analytics/event", { events: eventsToSend, }); } catch (error) { console.error("Failed to send events:", error); this.eventQueue = [...eventsToSend, ...this.eventQueue]; this.saveQueueToLocalStorage(); } } } export default EventQueue;