diff --git a/src/serviceWorker/assetCache.ts b/src/serviceWorker/assetCache.ts index 11bfd5944..3d15ceb59 100644 --- a/src/serviceWorker/assetCache.ts +++ b/src/serviceWorker/assetCache.ts @@ -1,12 +1,22 @@ import { ASSET_CACHE_NAME } from '../config'; +import { pause } from '../util/schedulers'; declare const self: ServiceWorkerGlobalScope; -export async function respondWithCache(e: FetchEvent) { - const cache = await self.caches.open(ASSET_CACHE_NAME); - const cached = await cache.match(e.request); +// An attempt to fix freezing UI on iOS +const CACHE_TIMEOUT = 3000; - if (cached) { +export async function respondWithCache(e: FetchEvent) { + const cacheResult = await withTimeout(async () => { + const cache = await self.caches.open(ASSET_CACHE_NAME); + const cached = await cache.match(e.request); + + return { cache, cached }; + }, CACHE_TIMEOUT); + + const { cache, cached } = cacheResult || {}; + + if (cache && cached) { if (cached.ok) { return cached; } else { @@ -16,13 +26,26 @@ export async function respondWithCache(e: FetchEvent) { const remote = await fetch(e.request); - if (remote.ok) { + if (remote.ok && cache) { cache.put(e.request, remote.clone()); } return remote; } +async function withTimeout(cb: () => Promise, timeout: number) { + try { + return await Promise.race([ + pause(timeout).then(() => Promise.reject(new Error('TIMEOUT'))), + cb(), + ]); + } catch (err) { + // eslint-disable-next-line no-console + console.error(err); + return undefined; + } +} + export function clearAssetCache() { return self.caches.delete(ASSET_CACHE_NAME); }