ultrascale-playbook / src /fragmentLoader.js
hynky's picture
hynky HF staff
fix optims (#56)
31ab930 verified
async function loadFragments() {
// Find all elements with ids starting with 'fragment-'
const fragmentElements = Array.from(document.querySelectorAll('[id^="fragment-"]'));
class FetchQueue {
constructor(maxConcurrent = 3) {
this.queue = [];
this.maxConcurrent = maxConcurrent;
this.activeFetches = 0;
this.maxRetries = 3; // Maximum number of retry attempts
this.baseDelay = 1000; // Base delay in milliseconds (1 second)
}
async sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async fetchWithRetry(fragmentPath, retryCount = 0) {
try {
const response = await fetch(fragmentPath);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.text();
} catch (error) {
if (retryCount < this.maxRetries) {
// Exponential backoff: 1s, 2s, 4s
const delay = this.baseDelay * Math.pow(2, retryCount);
console.warn(`Retry ${retryCount + 1}/${this.maxRetries} for ${fragmentPath} after ${delay}ms`);
await this.sleep(delay);
return this.fetchWithRetry(fragmentPath, retryCount + 1);
}
throw error;
}
}
async addFetch(element) {
const fragmentName = element.id.replace('fragment-', '');
const fragmentPath = `fragments/${fragmentName}.html`;
return new Promise(async (resolve, reject) => {
try {
const fetchPromise = (async () => {
try {
const html = await this.fetchWithRetry(fragmentPath);
// Process the fragment
const temp = document.createElement('div');
temp.innerHTML = html;
element.innerHTML = temp.innerHTML;
// Handle scripts
const scripts = temp.getElementsByTagName('script');
Array.from(scripts).forEach(oldScript => {
const newScript = document.createElement('script');
Array.from(oldScript.attributes).forEach(attr => {
newScript.setAttribute(attr.name, attr.value);
});
newScript.textContent = oldScript.textContent;
oldScript.parentNode.removeChild(oldScript);
document.body.appendChild(newScript);
});
this.activeFetches--;
resolve();
} catch (error) {
console.error(`Failed to load fragment ${fragmentPath} after ${this.maxRetries} retries:`, error);
this.activeFetches--;
reject(error);
}
})();
this.queue.push(fetchPromise);
this.activeFetches++;
} catch (error) {
reject(error);
}
});
}
async processNext(element) {
if (this.activeFetches < this.maxConcurrent && element) {
await this.addFetch(element);
}
}
}
// Initialize queue
const fetchQueue = new FetchQueue(3);
let currentIndex = 0;
const elements = fragmentElements; // Assuming this is defined elsewhere
// Initial loading of first 3 elements
while (currentIndex < elements.length && currentIndex < 3) {
await fetchQueue.processNext(elements[currentIndex]);
currentIndex++;
}
// Process remaining elements as fetches complete
while (currentIndex < elements.length) {
// Wait for any fetch to complete
await Promise.race(fetchQueue.queue);
// Remove completed fetch from queue
fetchQueue.queue = fetchQueue.queue.filter(p => p.status === 'pending');
// Add next element to queue
await fetchQueue.processNext(elements[currentIndex]);
currentIndex++;
}
// Wait for remaining fetches to complete
await Promise.all(fetchQueue.queue);
}
export { loadFragments }