diff --git a/apps/web/vue3/index.html b/apps/web/vue3/index.html index 71a2efe5e..e5276e079 100644 --- a/apps/web/vue3/index.html +++ b/apps/web/vue3/index.html @@ -14188,10 +14188,25 @@ compare: [[flesh, peel]]`; }; }; + const fetchWithTransientRetry = async (input, init = {}) => { + const retryDelays = [500, 1500]; + for (let attempt = 0; ; attempt += 1) { + try { + return await fetch(input, init); + } catch (err) { + const message = String(err?.message || err || ''); + const transient = err instanceof TypeError + || /NetworkError|Failed to fetch|Load failed/i.test(message); + if (!transient || attempt >= retryDelays.length) throw err; + await new Promise(resolve => setTimeout(resolve, retryDelays[attempt])); + } + } + }; + const pollReferenceBundleDownloadTask = async (taskId, options = {}) => { const intervalMs = Number(options.intervalMs || 3000); while (true) { - const response = await fetch(`/api/task/${encodeURIComponent(taskId)}`); + const response = await fetchWithTransientRetry(`/api/task/${encodeURIComponent(taskId)}`); const data = await response.json().catch(() => ({})); if (!response.ok) { throw new Error(referenceBundleErrorMessage(data, `Reference species data status request failed (HTTP ${response.status})`)); @@ -14533,7 +14548,7 @@ compare: [[flesh, peel]]`; if (requestedStages.length === 1 && requestedStages[0] === 'ppi') { canonicalizePpiOwnerBiologicalScope(payload); } - const response = await fetch('/api/ppi/species-resolution', { + const response = await fetchWithTransientRetry('/api/ppi/species-resolution', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) diff --git a/apps/web/vue3/index_ml.html b/apps/web/vue3/index_ml.html index 78e922879..4acfb84e4 100644 --- a/apps/web/vue3/index_ml.html +++ b/apps/web/vue3/index_ml.html @@ -5033,7 +5033,7 @@ -
+
{{ t('基本参数') }}
@@ -6575,12 +6575,21 @@ RNA-seq KEGG/fgsea 会优先使用物种级 KEGG gene set;没有物种级缓
+ +