diff --git a/benchmark_loadMenuDataFromAPI.js b/benchmark_loadMenuDataFromAPI.js new file mode 100644 index 0000000..7cc8a99 --- /dev/null +++ b/benchmark_loadMenuDataFromAPI.js @@ -0,0 +1,22 @@ +const fs = require('fs'); + +async function benchmark() { + // We will simulate the same exact loop in src/actions.js + let availableDates = Array.from({length: 30}).map((_, i) => ({ date: `2024-01-${i+1}`})); + const totalDates = availableDates.length; + let completed = 0; + + console.log(`Starting benchmark for ${totalDates} items (Sequential with 100ms artificial delay)`); + const start = Date.now(); + for (const dateObj of availableDates) { + // mock fetch + await new Promise(r => setTimeout(r, 50)); // simulate network delay + + completed++; + await new Promise(r => setTimeout(r, 100)); // the artificial delay in codebase + } + const end = Date.now(); + console.log(`Sequential loading took ${end - start}ms`); +} + +benchmark(); diff --git a/benchmark_loadMenuDataFromAPI_concurrent.js b/benchmark_loadMenuDataFromAPI_concurrent.js new file mode 100644 index 0000000..f63f2fd --- /dev/null +++ b/benchmark_loadMenuDataFromAPI_concurrent.js @@ -0,0 +1,26 @@ +const fs = require('fs'); + +async function benchmark() { + let availableDates = Array.from({length: 30}).map((_, i) => ({ date: `2024-01-${i+1}`})); + const totalDates = availableDates.length; + let completed = 0; + + console.log(`Starting benchmark for ${totalDates} items (Concurrent batch=5 without 100ms artificial delay)`); + const start = Date.now(); + + // Simulate Promise.all batching approach + const BATCH_SIZE = 5; + for (let i = 0; i < totalDates; i += BATCH_SIZE) { + const batch = availableDates.slice(i, i + BATCH_SIZE); + await Promise.all(batch.map(async (dateObj) => { + // mock fetch + await new Promise(r => setTimeout(r, 50)); // simulate network delay + completed++; + })); + } + + const end = Date.now(); + console.log(`Concurrent loading took ${end - start}ms`); +} + +benchmark(); diff --git a/dist/kantine.bundle.js b/dist/kantine.bundle.js index 8b8c0b3..5d2457b 100644 --- a/dist/kantine.bundle.js +++ b/dist/kantine.bundle.js @@ -783,41 +783,51 @@ async function loadMenuDataFromAPI() { const allDays = []; let completed = 0; - for (const dateObj of availableDates) { - const dateStr = dateObj.date; - const pct = Math.round(((completed + 1) / totalDates) * 100); - progressFill.style.width = `${pct}%`; - progressPercent.textContent = `${pct}%`; - progressMessage.textContent = `Lade Menü für ${dateStr}...`; + const BATCH_SIZE = 5; + for (let i = 0; i < totalDates; i += BATCH_SIZE) { + const batch = availableDates.slice(i, i + BATCH_SIZE); + const results = await Promise.all(batch.map(async (dateObj) => { + const dateStr = dateObj.date; + let dayData = null; + try { + const detailResp = await fetch(`${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .API_BASE */ .tE}/venues/${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .VENUE_ID */ .eW}/menu/${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MENU_ID */ .YU}/${dateStr}/`, { + headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .apiHeaders */ .H)(token) + }); - try { - const detailResp = await fetch(`${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .API_BASE */ .tE}/venues/${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .VENUE_ID */ .eW}/menu/${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MENU_ID */ .YU}/${dateStr}/`, { - headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .apiHeaders */ .H)(token) - }); - - if (detailResp.ok) { - const detailData = await detailResp.json(); - const menuGroups = detailData.results || []; - let dayItems = []; - for (const group of menuGroups) { - if (group.items && Array.isArray(group.items)) { - dayItems = dayItems.concat(group.items); + if (detailResp.ok) { + const detailData = await detailResp.json(); + const menuGroups = detailData.results || []; + let dayItems = []; + for (const group of menuGroups) { + if (group.items && Array.isArray(group.items)) { + dayItems = dayItems.concat(group.items); + } + } + if (dayItems.length > 0) { + dayData = { + date: dateStr, + menu_items: dayItems, + orders: dateObj.orders || [] + }; } } - if (dayItems.length > 0) { - allDays.push({ - date: dateStr, - menu_items: dayItems, - orders: dateObj.orders || [] - }); - } + } catch (err) { + console.error(`Failed to fetch details for ${dateStr}:`, err); + } finally { + completed++; + const pct = Math.round((completed / totalDates) * 100); + progressFill.style.width = `${pct}%`; + progressPercent.textContent = `${pct}%`; + progressMessage.textContent = `Lade Menü für ${dateStr}...`; } - } catch (err) { - console.error(`Failed to fetch details for ${dateStr}:`, err); - } + return dayData; + })); - completed++; - await new Promise(r => setTimeout(r, 100)); + for (const result of results) { + if (result) { + allDays.push(result); + } + } } const weeksMap = new Map(); diff --git a/src/actions.js b/src/actions.js index 2ea10b4..c5bd1ee 100644 --- a/src/actions.js +++ b/src/actions.js @@ -753,41 +753,51 @@ export async function loadMenuDataFromAPI() { const allDays = []; let completed = 0; - for (const dateObj of availableDates) { - const dateStr = dateObj.date; - const pct = Math.round(((completed + 1) / totalDates) * 100); - progressFill.style.width = `${pct}%`; - progressPercent.textContent = `${pct}%`; - progressMessage.textContent = `Lade Menü für ${dateStr}...`; + const BATCH_SIZE = 5; + for (let i = 0; i < totalDates; i += BATCH_SIZE) { + const batch = availableDates.slice(i, i + BATCH_SIZE); + const results = await Promise.all(batch.map(async (dateObj) => { + const dateStr = dateObj.date; + let dayData = null; + try { + const detailResp = await fetch(`${API_BASE}/venues/${VENUE_ID}/menu/${MENU_ID}/${dateStr}/`, { + headers: apiHeaders(token) + }); - try { - const detailResp = await fetch(`${API_BASE}/venues/${VENUE_ID}/menu/${MENU_ID}/${dateStr}/`, { - headers: apiHeaders(token) - }); - - if (detailResp.ok) { - const detailData = await detailResp.json(); - const menuGroups = detailData.results || []; - let dayItems = []; - for (const group of menuGroups) { - if (group.items && Array.isArray(group.items)) { - dayItems = dayItems.concat(group.items); + if (detailResp.ok) { + const detailData = await detailResp.json(); + const menuGroups = detailData.results || []; + let dayItems = []; + for (const group of menuGroups) { + if (group.items && Array.isArray(group.items)) { + dayItems = dayItems.concat(group.items); + } + } + if (dayItems.length > 0) { + dayData = { + date: dateStr, + menu_items: dayItems, + orders: dateObj.orders || [] + }; } } - if (dayItems.length > 0) { - allDays.push({ - date: dateStr, - menu_items: dayItems, - orders: dateObj.orders || [] - }); - } + } catch (err) { + console.error(`Failed to fetch details for ${dateStr}:`, err); + } finally { + completed++; + const pct = Math.round((completed / totalDates) * 100); + progressFill.style.width = `${pct}%`; + progressPercent.textContent = `${pct}%`; + progressMessage.textContent = `Lade Menü für ${dateStr}...`; } - } catch (err) { - console.error(`Failed to fetch details for ${dateStr}:`, err); - } + return dayData; + })); - completed++; - await new Promise(r => setTimeout(r, 100)); + for (const result of results) { + if (result) { + allDays.push(result); + } + } } const weeksMap = new Map();