1/** 2 * Race a promise against a timeout. 3 * 4 * One settle-once timer guards two contracts, selected by `rejectOnTimeout`: 5 * 6 * resolve-mode (default): resolve to the promise's value, or to `fallback` 7 * if it rejects or does not settle within `ms`. Never rejects. Bounds a 8 * check that must not stall work a fallback can already satisfy 9 * (archiveService's version check). 10 * 11 * reject-mode (`rejectOnTimeout: true`): resolve to the promise's value; 12 * reject with the promise's own error if it rejects, or with a timeout 13 * Error if it does not settle within `ms`. Surfaces a stall as a failure 14 * the caller can fall back from (idbCache's idb-keyval import race). 15 * 16 * The timer is intentionally left ref'd: an unref'd timer that is the only 17 * pending work never fires (the event loop idles past it), so a hung promise 18 * would never time out. It is cleared as soon as either side settles. 19 * 20 * @template T 21 * @param {Promise<T>} promise 22 * @param {number} ms 23 * @param {{ fallback?: T, rejectOnTimeout?: boolean }} [options] 24 * @returns {Promise<T>} 25 */ 26export const raceTimeout = (promise, ms, { fallback, rejectOnTimeout = false } = {}) => 27 new Promise((resolve, reject) => { 28 let settled = false; 29 const finishResolve = (value) => { 30 if (settled) return; 31 settled = true; 32 clearTimeout(timer); 33 resolve(value); 34 }; 35 const finishReject = (err) => { 36 if (settled) return; 37 settled = true; 38 clearTimeout(timer); 39 reject(err); 40 }; 41 const timer = setTimeout(() => { 42 if (rejectOnTimeout) finishReject(new Error(`timed out after ${ms}ms`)); 43 else finishResolve(fallback); 44 }, ms); 45 promise.then( 46 finishResolve, 47 (err) => (rejectOnTimeout ? finishReject(err) : finishResolve(fallback)), 48 ); 49 });
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.