From 3dc1d4397630bce554cffc7309ad8aced10c9e57 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 25 May 2023 10:15:41 +0300 Subject: [PATCH] mount_css: add timeout; use it for external CSS Refs #4332 (part of it anyway) --- CHANGELOG.md | 3 ++- js/app/src/Index.svelte | 2 ++ js/app/src/css.ts | 27 +++++++++++++++++++++------ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1cb61049dd82..0d67a18462219 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ No changes to highlight. ## Bug Fixes: -No changes to highlight. +- Gradio will no longer hang forever when waiting for external CSS to load by [@akx](https://github.com/akx) in [PR 4335](https://github.com/gradio-app/gradio/pull/4335) + ## Other Changes: diff --git a/js/app/src/Index.svelte b/js/app/src/Index.svelte index 71fc84f3224ae..dd8278431e3f7 100644 --- a/js/app/src/Index.svelte +++ b/js/app/src/Index.svelte @@ -109,6 +109,8 @@ stylesheet.startsWith("http:") || stylesheet.startsWith("https:"); return mount_css( absolute_link ? stylesheet : config.root + "/" + stylesheet, + // Wait up to 1.5 seconds for external stylesheets to load before continuing anyway. + absolute_link ? 1500 : undefined ); }) ); diff --git a/js/app/src/css.ts b/js/app/src/css.ts index b05f7696e2245..c66778a1d9571 100644 --- a/js/app/src/css.ts +++ b/js/app/src/css.ts @@ -1,4 +1,12 @@ -export function mount_css(url: string): Promise { +/** + * Loads a CSS file and appends it to the document head. + * The optional timeout parameter will resolve the promise without error + * if the CSS file has not loaded after the specified time. + * + * @param url URL to load. + * @param timeout Optional timeout, in milliseconds. + */ +export function mount_css(url: string, timeout?: number): Promise { const existing_link = document.querySelector(`link[href='${url}']`); if (existing_link) return Promise.resolve(); @@ -8,10 +16,17 @@ export function mount_css(url: string): Promise { link.href = url; document.head.appendChild(link); - return new Promise((res, rej) => { - link.addEventListener("load", () => res()); - link.addEventListener("error", () => - rej(new Error(`Unable to preload CSS for ${url}`)) - ); + const loadPromise = new Promise((res, rej) => { + link.addEventListener("load", res); + link.addEventListener("error", (err) => { + console.error(`load_css: failed to load CSS`, url, err); + rej(err); + }); }); + + if (timeout) { + const timeoutPromise = new Promise((res) => setTimeout(res, timeout)); + return Promise.race([loadPromise, timeoutPromise]); + } + return loadPromise; }