Skip to content

Commit 564f5b8

Browse files
committed
WIP
1 parent 8cd0cdc commit 564f5b8

File tree

6 files changed

+41
-2
lines changed

6 files changed

+41
-2
lines changed

packages/sdk/browser/src/BrowserClient.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import GoalManager from './goals/GoalManager';
2121
import { Goal, isClick } from './goals/Goals';
2222
import validateOptions, { BrowserOptions, filterToBaseOptions } from './options';
2323
import 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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
}

packages/sdk/browser/src/options.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import {
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+
6976
export 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];

packages/shared/common/src/api/platform/Requests.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff 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

8186
export interface EventSourceCapabilities {

packages/shared/common/src/internal/events/EventSender.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff 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') || '');

packages/shared/sdk-client/src/api/LDOptions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff 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

0 commit comments

Comments
 (0)