| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- // utils.ts
- // 带重试机制的 fetch 封装
- const fetchWithRetry = async (url: string, options: RequestInit, maxRetries = 3, delay = 1000): Promise<Response> => {
- let lastError: Error;
- for (let i = 0; i <= maxRetries; i++) {
- try {
- const response = await fetch(url, options);
- if (response.status === 429) {
- if (i < maxRetries) {
- const retryDelay = delay * Math.pow(2, i) + Math.random() * 1000; // 指数退避+随机抖动
- await new Promise(resolve => setTimeout(resolve, retryDelay));
- continue;
- } else {
- throw new Error(`Too Many Requests (429). Max retries exceeded.`);
- }
- }
- if (!response.ok) {
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
- }
- return response;
- } catch (error) {
- lastError = error as Error;
- if (i < maxRetries) {
- const retryDelay = delay * Math.pow(2, i) + Math.random() * 1000;
- await new Promise(resolve => setTimeout(resolve, retryDelay));
- }
- }
- }
- throw lastError!;
- };
- export const urlToBlob = async (url: string): Promise<Blob> => {
- try {
- const response = await fetchWithRetry(url, {
- headers: {
- "accept": 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8'
- }
- }, 3, 2000); // 最多重试3次,基础延迟2秒
- return await response.blob();
- } catch (error) {
- console.error(`获取图片失败 (${url}):`, error);
- throw error;
- }
- };
- export const urlToFile = async (url: string, fileName: string): Promise<File | null> => {
- try {
- const blob = await urlToBlob(url);
- return new File([blob], fileName, {
- type: blob.type,
- lastModified: new Date().getTime()
- });
- } catch (error) {
- console.error(`图片转文件失败 (${url}):`, error);
- return null;
- }
- };
- // export const urlToBlob = async (url: string): Promise<Blob> => {
- // return new Promise(async (resolve, reject) => {
- // const response = await fetch(url, {
- // headers: {
- // "accept": 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8'
- // }
- // });
- // if (!response.ok) {
- // reject(null)
- // };
- // resolve(await response.blob() as Blob); // 显式断言为 Blob 类型
- // return
- // const xhr = new XMLHttpRequest();
- // xhr.open("GET", url, true);
- // xhr.responseType = "blob";
- // xhr.onload = function () {
- // if (this.status === 200) {
- // resolve(this.response as Blob); // 显式断言为 Blob 类型
- // } else {
- // reject(new Error("Error loading image"));
- // }
- // };
- // xhr.onerror = function () {
- // reject(new Error("Network error"));
- // };
- // xhr.send();
- // });
- // };
- // export const urlToFile = async (url: string, fileName: string) => {
- // console.log("urlToFile")
- // return urlToBlob(url).then(blob => {
- // if (!blob) return null;
- // return new File([blob], fileName, {
- // type: blob.type,
- // lastModified: new Date().getTime()
- // });
- // }).catch(error => {
- // return null;
- // })
- // }
|