UNPKG

@dash0/sdk-web

Version:

Dash0's Web SDK to collect telemetry from end-users' web browsers

60 lines (50 loc) 1.83 kB
import { onLastChance } from "../utils/on-last-chance"; import { doc } from "../utils"; import { setTimeout } from "../utils/timers"; const SCHEDULE_DELAY_MILLIS = 1000; const MAX_QUEUE_SIZE = 15; export type Batcher<T> = { send(item: T): void; }; export function newBatcher<T>(sendInternal: (items: T[]) => void): Batcher<T> { const queuedItems: T[] = []; let pendingFlushTimeout: ReturnType<typeof setTimeout> | null; // We attempt batching of messages to be more efficient on the client, network and // server-side. While the connection is either a persistent HTTP 2 connection or // an HTTP 1.1 connection with keep-alive, there is still some overhead involved // in having many small messages. // // For this reason we attempt batching. When batching we must be careful to // force a transmission when the document is unloaded. onLastChance(flush); return { send(item: T): void { if (isWindowHidden()) { // We cannot guarantee that we will ever get time to transmit data in a batched // format when the window is hidden, as this might occur while the document is // being unloaded. Immediately force a transmission in these cases. sendInternal([item]); return; } queuedItems.push(item); if (queuedItems.length >= MAX_QUEUE_SIZE) { flush(); } else if (pendingFlushTimeout == null) { pendingFlushTimeout = setTimeout(flush, SCHEDULE_DELAY_MILLIS); } }, }; function flush() { if (pendingFlushTimeout != null) { clearTimeout(pendingFlushTimeout); pendingFlushTimeout = null; } if (queuedItems.length > 0) { sendInternal(queuedItems.slice()); queuedItems.length = 0; } } } function isWindowHidden() { return doc?.visibilityState !== "visible"; }