Analyse: verspätete Statistik-Antwort überschreibt den Stand nicht mehr
loadStats schrieb state.stats/range/stamp schon beim Eintreffen der Antwort, vor der current()-Prüfung der Aufrufer. Eine späte 30-Tage-Antwort überschrieb so den 7-Tage-Stand, und "Alle anzeigen" oder der Ranglisten-Umschalter malte danach mit 30-Tage-Zahlen. Jetzt liefert fetchStats nur die Antwort, adopt() übernimmt sie erst nach current(). Übersicht und Heatmap teilen sich eine laufende Anfrage je Zeitraum. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a9f0711e97
commit
eadb768d1a
2 files changed
+39
-8
No files matched your search
+19
-5
@@ -196,12 +196,22 @@ function mountCockpit({ an, stage, project, usable, reload }) {
|
||||
})
|
||||
stage.setAttribute('aria-labelledby', `an-tab-${tab}`)
|
||||
}
|
||||
async function loadStats(range) {
|
||||
const stats = await request(`/api/funktionen/analyse/stats?projectId=${encodeURIComponent(pid)}&range=${range}`)
|
||||
// Anfrage je Zeitraum: Uebersicht und Heatmap teilen sich eine laufende Anfrage. Sie schreibt nichts in state; uebernommen
|
||||
// (adopt) wird die Antwort erst nach current(mine), sonst ueberschriebe eine verspaetete den Stand des neueren Zeitraums.
|
||||
const pending = {}
|
||||
function fetchStats(range) {
|
||||
if (!pending[range]) {
|
||||
const p = request(`/api/funktionen/analyse/stats?projectId=${encodeURIComponent(pid)}&range=${range}`)
|
||||
const done = () => { if (pending[range] === p) delete pending[range] }
|
||||
p.then(done, done)
|
||||
pending[range] = p
|
||||
}
|
||||
return pending[range]
|
||||
}
|
||||
function adopt(stats, range) {
|
||||
state.stats = stats
|
||||
state.range = range
|
||||
state.stamp = CLOCK.format(new Date())
|
||||
return stats
|
||||
}
|
||||
|
||||
function paintOverview() {
|
||||
@@ -224,14 +234,16 @@ function mountCockpit({ an, stage, project, usable, reload }) {
|
||||
return
|
||||
}
|
||||
stage.innerHTML = skeletonHtml()
|
||||
let stats
|
||||
try {
|
||||
await loadStats(range)
|
||||
stats = await fetchStats(range)
|
||||
} catch (err) {
|
||||
if (!current(mine)) return
|
||||
stage.innerHTML = errorHtml(err.status === 503 ? 'Auswertung gerade nicht erreichbar' : err.message)
|
||||
return
|
||||
}
|
||||
if (!current(mine)) return
|
||||
adopt(stats, range)
|
||||
paintHead()
|
||||
paintOverview()
|
||||
}
|
||||
@@ -242,14 +254,16 @@ function mountCockpit({ an, stage, project, usable, reload }) {
|
||||
const box = stage.querySelector('#an-heat')
|
||||
if (!state.stats) {
|
||||
box.innerHTML = '<h3>Heatmap</h3><p class="an-empty">Lade…</p>'
|
||||
let stats
|
||||
try {
|
||||
await loadStats(30)
|
||||
stats = await fetchStats(30)
|
||||
} catch (err) {
|
||||
if (!current(mine)) return
|
||||
stage.innerHTML = errorHtml(err.status === 503 ? 'Auswertung gerade nicht erreichbar' : err.message)
|
||||
return
|
||||
}
|
||||
if (!current(mine)) return
|
||||
adopt(stats, 30)
|
||||
paintHead()
|
||||
}
|
||||
renderAnalyseHeat(box, pid, state.stats.pages || [])
|
||||
|
||||
Reference in new issue
Block a user