/** * External dependencies */ import { parse as cookieParse } from 'cookie'; let initializeAnonIdPromise: Promise< string | null > | null = null; const anonIdPollingIntervalMilliseconds = 50; const anonIdPollingIntervalMaxAttempts = 100; // 50 * 100 = 5000 = 5 seconds /** * Gather w.js anonymous cookie, tk_ai * * @return {?string} The anonymous cookie value, or null if it doesn't exist */ export const readAnonCookie = (): string | null => { return cookieParse( document.cookie ).tk_ai || null; }; /** * Initializes the anonId: * - Polls for AnonId receival * - Should only be called once at startup * - Happens to be safe to call multiple times if it is necessary to reset the anonId - something like this was necessary for testing. * * This purely for boot-time initialization, in usual circumstances it will be retrieved within 100-300ms, it happens in parallel booting * so should only delay experiment loading that much for boot-time experiments. In some circumstances such as a very slow connection this * can take a lot longer. * * The state of initializeAnonIdPromise should be used rather than the return of this function. * The return is only avaliable to make this easier to test. * * Throws on error. * * @return {Promise} The anonymous cookie value, or null if it doesn't exist */ export const initializeAnonId = async (): Promise< string | null > => { let attempt = 0; initializeAnonIdPromise = new Promise( res => { const poll = () => { const anonId = readAnonCookie(); if ( typeof anonId === 'string' && anonId !== '' ) { res( anonId ); return; } if ( anonIdPollingIntervalMaxAttempts - 1 <= attempt ) { res( null ); return; } attempt += 1; setTimeout( poll, anonIdPollingIntervalMilliseconds ); }; poll(); } ); return initializeAnonIdPromise; }; export const getAnonId = async (): Promise< string | null > => { return await initializeAnonIdPromise; };