Files
2026-02-27 16:02:44 +04:00

65 lines
1.6 KiB
JavaScript

import { ref } from 'vue';
export const useLoadWithRetry = (config = {}) => {
const maxRetry = (config.max_retry ?? config.maxRetry) || 3;
const backoff = (config.backoff ?? config.backOff) || 1000;
const mediaType = (config.mediaType ?? config.media_type) || 'image';
const isLoaded = ref(false);
const hasError = ref(false);
const loadWithRetry = async url => {
const attemptLoad = () => {
return new Promise((resolve, reject) => {
const onSuccess = () => {
isLoaded.value = true;
hasError.value = false;
resolve();
};
let element;
if (mediaType === 'audio') {
element = new Audio();
element.preload = 'metadata';
element.onloadedmetadata = onSuccess;
} else {
element = new Image();
element.onload = onSuccess;
}
element.onerror = () => reject(new Error('Failed to load resource'));
const cacheBustedUrl = new URL(url);
cacheBustedUrl.searchParams.set('t', Date.now());
element.src = cacheBustedUrl.toString();
});
};
const sleep = ms => {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
};
const retry = async (attempt = 0) => {
try {
await attemptLoad();
} catch (error) {
if (attempt + 1 >= maxRetry) {
hasError.value = true;
isLoaded.value = false;
return;
}
await sleep(backoff * (attempt + 1));
await retry(attempt + 1);
}
};
await retry();
};
return {
isLoaded,
hasError,
loadWithRetry,
};
};