File tree Expand file tree Collapse file tree 6 files changed +41
-2
lines changed Expand file tree Collapse file tree 6 files changed +41
-2
lines changed Original file line number Diff line number Diff line change @@ -21,6 +21,7 @@ import GoalManager from './goals/GoalManager';
2121import { Goal , isClick } from './goals/Goals' ;
2222import validateOptions , { BrowserOptions , filterToBaseOptions } from './options' ;
2323import BrowserPlatform from './platform/BrowserPlatform' ;
24+ import { registerStateDetection } from './BrowserStateDetector' ;
2425
2526/**
2627 *
@@ -211,6 +212,8 @@ export class BrowserClient extends LDClientImpl implements LDClient {
211212 // which emits the event, and assign its promise to a member. The "waitForGoalsReady" function
212213 // would return that promise.
213214 this . goalManager . initialize ( ) ;
215+
216+ registerStateDetection ( ( ) => this . flush ( ) ) ;
214217 }
215218 }
216219
Original file line number Diff line number Diff line change 1+ export function registerStateDetection ( requestFlush : ( ) => void ) {
2+ // When the visibility of the page changes to hidden we want to flush any pending events.
3+ //
4+ // This is handled with visibility, instead of beforeunload/unload
5+ // because those events are not compatible with the bfcache and are unlikely
6+ // to be called in many situations. For more information see: https://developer.chrome.com/blog/page-lifecycle-api/
7+ //
8+ // Redundancy is included by using both the visibilitychange handler as well as
9+ // pagehide, because different browsers, and versions have different bugs with each.
10+ // This also may provide more opportunity for the events to get flushed.
11+ //
12+ const handleVisibilityChange = ( ) => {
13+ if ( document . visibilityState === 'hidden' ) {
14+ requestFlush ( ) ;
15+ }
16+ } ;
17+
18+ document . addEventListener ( 'visibilitychange' , handleVisibilityChange ) ;
19+ window . addEventListener ( 'pagehide' , requestFlush ) ;
20+ }
Original file line number Diff line number Diff line change 66 TypeValidators ,
77} from '@launchdarkly/js-client-sdk-common' ;
88
9+ const DEFAULT_FLUSH_INTERVAL_SECONDS = 2 ;
10+
911/**
1012 * Initialization options for the LaunchDarkly browser SDK.
1113 */
@@ -66,8 +68,14 @@ export function filterToBaseOptions(opts: BrowserOptions): LDOptionsBase {
6668 return baseOptions ;
6769}
6870
71+ function applyBrowserDefaults ( opts : BrowserOptions ) {
72+ // eslint-disable-next-line no-param-reassign
73+ opts . flushInterval ??= DEFAULT_FLUSH_INTERVAL_SECONDS ;
74+ }
75+
6976export default function validateOptions ( opts : BrowserOptions , logger : LDLogger ) : ValidatedOptions {
7077 const output : ValidatedOptions = { ...optDefaults } ;
78+ applyBrowserDefaults ( output ) ;
7179
7280 Object . entries ( validators ) . forEach ( ( entry ) => {
7381 const [ key , validator ] = entry as [ keyof BrowserOptions , TypeValidator ] ;
Original file line number Diff line number Diff line change @@ -76,6 +76,11 @@ export interface Options {
7676 method ?: string ;
7777 body ?: string ;
7878 timeout ?: number ;
79+ /**
80+ * For use in browser environments. Platform support will be best effort for this field.
81+ * https://developer.mozilla.org/en-US/docs/Web/API/RequestInit#keepalive
82+ */
83+ keepalive ?: boolean ;
7984}
8085
8186export interface EventSourceCapabilities {
Original file line number Diff line number Diff line change @@ -65,6 +65,9 @@ export default class EventSender implements LDEventSender {
6565 headers,
6666 body : JSON . stringify ( events ) ,
6767 method : 'POST' ,
68+ // When sending events from browser environments the request should be completed even
69+ // if the user is navigating away from the page.
70+ keepalive : true ,
6871 } ) ;
6972
7073 const serverDate = Date . parse ( resHeaders . get ( 'date' ) || '' ) ;
Original file line number Diff line number Diff line change @@ -111,9 +111,9 @@ export interface LDOptions {
111111 eventsUri ?: string ;
112112
113113 /**
114- * Controls how often the SDK flushes events.
114+ * The interval in between flushes of the analytics events queue, in seconds .
115115 *
116- * @defaultValue 30s.
116+ * @defaultValue 2s for browser implementations 30s for others .
117117 */
118118 flushInterval ?: number ;
119119
You can’t perform that action at this time.
0 commit comments