⚡ performance optimization: batch fetch availableDates
Removed the 100ms artificial delay in `loadMenuDataFromAPI` and switched from sequentially awaiting fetch requests to concurrently awaiting requests in batches of 5 using `Promise.all`. Preserved original chronological ordering of array elements. Co-authored-by: TauNeutrino <1600410+TauNeutrino@users.noreply.github.com>
This commit is contained in:
22
benchmark_loadMenuDataFromAPI.js
Normal file
22
benchmark_loadMenuDataFromAPI.js
Normal file
@@ -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();
|
||||||
26
benchmark_loadMenuDataFromAPI_concurrent.js
Normal file
26
benchmark_loadMenuDataFromAPI_concurrent.js
Normal file
@@ -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();
|
||||||
70
dist/kantine.bundle.js
vendored
70
dist/kantine.bundle.js
vendored
@@ -783,41 +783,51 @@ async function loadMenuDataFromAPI() {
|
|||||||
const allDays = [];
|
const allDays = [];
|
||||||
let completed = 0;
|
let completed = 0;
|
||||||
|
|
||||||
for (const dateObj of availableDates) {
|
const BATCH_SIZE = 5;
|
||||||
const dateStr = dateObj.date;
|
for (let i = 0; i < totalDates; i += BATCH_SIZE) {
|
||||||
const pct = Math.round(((completed + 1) / totalDates) * 100);
|
const batch = availableDates.slice(i, i + BATCH_SIZE);
|
||||||
progressFill.style.width = `${pct}%`;
|
const results = await Promise.all(batch.map(async (dateObj) => {
|
||||||
progressPercent.textContent = `${pct}%`;
|
const dateStr = dateObj.date;
|
||||||
progressMessage.textContent = `Lade Menü für ${dateStr}...`;
|
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 {
|
if (detailResp.ok) {
|
||||||
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}/`, {
|
const detailData = await detailResp.json();
|
||||||
headers: (0,_api_js__WEBPACK_IMPORTED_MODULE_3__/* .apiHeaders */ .H)(token)
|
const menuGroups = detailData.results || [];
|
||||||
});
|
let dayItems = [];
|
||||||
|
for (const group of menuGroups) {
|
||||||
if (detailResp.ok) {
|
if (group.items && Array.isArray(group.items)) {
|
||||||
const detailData = await detailResp.json();
|
dayItems = dayItems.concat(group.items);
|
||||||
const menuGroups = detailData.results || [];
|
}
|
||||||
let dayItems = [];
|
}
|
||||||
for (const group of menuGroups) {
|
if (dayItems.length > 0) {
|
||||||
if (group.items && Array.isArray(group.items)) {
|
dayData = {
|
||||||
dayItems = dayItems.concat(group.items);
|
date: dateStr,
|
||||||
|
menu_items: dayItems,
|
||||||
|
orders: dateObj.orders || []
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dayItems.length > 0) {
|
} catch (err) {
|
||||||
allDays.push({
|
console.error(`Failed to fetch details for ${dateStr}:`, err);
|
||||||
date: dateStr,
|
} finally {
|
||||||
menu_items: dayItems,
|
completed++;
|
||||||
orders: dateObj.orders || []
|
const pct = Math.round((completed / totalDates) * 100);
|
||||||
});
|
progressFill.style.width = `${pct}%`;
|
||||||
}
|
progressPercent.textContent = `${pct}%`;
|
||||||
|
progressMessage.textContent = `Lade Menü für ${dateStr}...`;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
return dayData;
|
||||||
console.error(`Failed to fetch details for ${dateStr}:`, err);
|
}));
|
||||||
}
|
|
||||||
|
|
||||||
completed++;
|
for (const result of results) {
|
||||||
await new Promise(r => setTimeout(r, 100));
|
if (result) {
|
||||||
|
allDays.push(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const weeksMap = new Map();
|
const weeksMap = new Map();
|
||||||
|
|||||||
@@ -752,41 +752,51 @@ export async function loadMenuDataFromAPI() {
|
|||||||
const allDays = [];
|
const allDays = [];
|
||||||
let completed = 0;
|
let completed = 0;
|
||||||
|
|
||||||
for (const dateObj of availableDates) {
|
const BATCH_SIZE = 5;
|
||||||
const dateStr = dateObj.date;
|
for (let i = 0; i < totalDates; i += BATCH_SIZE) {
|
||||||
const pct = Math.round(((completed + 1) / totalDates) * 100);
|
const batch = availableDates.slice(i, i + BATCH_SIZE);
|
||||||
progressFill.style.width = `${pct}%`;
|
const results = await Promise.all(batch.map(async (dateObj) => {
|
||||||
progressPercent.textContent = `${pct}%`;
|
const dateStr = dateObj.date;
|
||||||
progressMessage.textContent = `Lade Menü für ${dateStr}...`;
|
let dayData = null;
|
||||||
|
try {
|
||||||
|
const detailResp = await fetch(`${API_BASE}/venues/${VENUE_ID}/menu/${MENU_ID}/${dateStr}/`, {
|
||||||
|
headers: apiHeaders(token)
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
if (detailResp.ok) {
|
||||||
const detailResp = await fetch(`${API_BASE}/venues/${VENUE_ID}/menu/${MENU_ID}/${dateStr}/`, {
|
const detailData = await detailResp.json();
|
||||||
headers: apiHeaders(token)
|
const menuGroups = detailData.results || [];
|
||||||
});
|
let dayItems = [];
|
||||||
|
for (const group of menuGroups) {
|
||||||
if (detailResp.ok) {
|
if (group.items && Array.isArray(group.items)) {
|
||||||
const detailData = await detailResp.json();
|
dayItems = dayItems.concat(group.items);
|
||||||
const menuGroups = detailData.results || [];
|
}
|
||||||
let dayItems = [];
|
}
|
||||||
for (const group of menuGroups) {
|
if (dayItems.length > 0) {
|
||||||
if (group.items && Array.isArray(group.items)) {
|
dayData = {
|
||||||
dayItems = dayItems.concat(group.items);
|
date: dateStr,
|
||||||
|
menu_items: dayItems,
|
||||||
|
orders: dateObj.orders || []
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dayItems.length > 0) {
|
} catch (err) {
|
||||||
allDays.push({
|
console.error(`Failed to fetch details for ${dateStr}:`, err);
|
||||||
date: dateStr,
|
} finally {
|
||||||
menu_items: dayItems,
|
completed++;
|
||||||
orders: dateObj.orders || []
|
const pct = Math.round((completed / totalDates) * 100);
|
||||||
});
|
progressFill.style.width = `${pct}%`;
|
||||||
}
|
progressPercent.textContent = `${pct}%`;
|
||||||
|
progressMessage.textContent = `Lade Menü für ${dateStr}...`;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
return dayData;
|
||||||
console.error(`Failed to fetch details for ${dateStr}:`, err);
|
}));
|
||||||
}
|
|
||||||
|
|
||||||
completed++;
|
for (const result of results) {
|
||||||
await new Promise(r => setTimeout(r, 100));
|
if (result) {
|
||||||
|
allDays.push(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const weeksMap = new Map();
|
const weeksMap = new Map();
|
||||||
|
|||||||
Reference in New Issue
Block a user