Stream results progressively via SSE instead of waiting for full render
The loading page now opens an EventSource to a new ?render=stream endpoint. The server immediately sends a shell event (full page chrome: nav, filters, JS — no external fetches needed), then a section event per direction as each one's NR + Eurostar data arrives, and finally a done event with the summary and timetable-refresh URL. The client slots each section card into a placeholder and calls initialiseResultsPage() only after done, so fares and advance-fare streaming start at the right moment. Adds results_shell.html (shell template with empty JS data globals and mergeSectionData/finaliseResults hooks), results_section.html (extracted section card partial used by both the full and stream render paths), and helper functions _section_trip_fares() and _build_summary_html() to avoid duplicating fare-dict assembly between the two paths. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5f0d2c71b1
commit
453d6244ec
5 changed files with 1182 additions and 197 deletions
|
|
@ -51,33 +51,64 @@
|
|||
});
|
||||
}
|
||||
|
||||
function showError() {
|
||||
var panel = document.querySelector('.loading-panel');
|
||||
if (panel) {
|
||||
panel.innerHTML = '<div><strong>Could not load results</strong><p class="text-muted text-sm"><a href="{{ full_results_url }}">Try loading the full results page</a>.</p></div>';
|
||||
}
|
||||
}
|
||||
|
||||
function loadResults() {
|
||||
if (!window.EventSource) {
|
||||
window.location.href = {{ full_results_url|tojson }};
|
||||
return;
|
||||
}
|
||||
|
||||
attempts += 1;
|
||||
fetch({{ full_results_url|tojson }}, {headers: {'X-Requested-With': 'fetch'}})
|
||||
.then(function(response) {
|
||||
if (!response.ok) throw new Error('Could not load results');
|
||||
return response.text();
|
||||
})
|
||||
.then(function(html) {
|
||||
var doc = new DOMParser().parseFromString(html, 'text/html');
|
||||
var source = new EventSource({{ stream_url|tojson }});
|
||||
|
||||
source.onmessage = function(event) {
|
||||
var msg;
|
||||
try { msg = JSON.parse(event.data); } catch(e) { return; }
|
||||
|
||||
if (msg.type === 'shell') {
|
||||
var doc = new DOMParser().parseFromString(msg.html, 'text/html');
|
||||
document.title = doc.title;
|
||||
var nextMain = doc.querySelector('main');
|
||||
var currentMain = document.querySelector('main');
|
||||
if (!nextMain || !currentMain) throw new Error('Results page was incomplete');
|
||||
if (!nextMain || !currentMain) { source.close(); return; }
|
||||
currentMain.innerHTML = nextMain.innerHTML;
|
||||
runScripts(currentMain);
|
||||
history.replaceState(null, '', window.location.href);
|
||||
})
|
||||
.catch(function() {
|
||||
if (attempts < 3) {
|
||||
window.setTimeout(loadResults, attempts * 2000);
|
||||
return;
|
||||
|
||||
} else if (msg.type === 'section') {
|
||||
var placeholder = document.getElementById('section-placeholder-' + msg.id);
|
||||
if (placeholder) {
|
||||
var tmp = document.createElement('div');
|
||||
tmp.innerHTML = msg.html;
|
||||
var card = tmp.firstElementChild;
|
||||
if (card) placeholder.parentNode.replaceChild(card, placeholder);
|
||||
}
|
||||
var panel = document.querySelector('.loading-panel');
|
||||
if (panel) {
|
||||
panel.innerHTML = '<div><strong>Could not load results</strong><p class="text-muted text-sm"><a href="{{ full_results_url }}">Try loading the full results page</a>.</p></div>';
|
||||
}
|
||||
});
|
||||
if (typeof mergeSectionData === 'function') mergeSectionData(msg);
|
||||
|
||||
} else if (msg.type === 'done') {
|
||||
if (typeof finaliseResults === 'function') finaliseResults(msg);
|
||||
source.close();
|
||||
|
||||
} else if (msg.type === 'error') {
|
||||
source.close();
|
||||
showError();
|
||||
}
|
||||
};
|
||||
|
||||
source.onerror = function() {
|
||||
source.close();
|
||||
if (attempts < 3) {
|
||||
window.setTimeout(loadResults, attempts * 2000);
|
||||
} else {
|
||||
showError();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
loadResults();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue