实现图片本地缓存,减少url重复请求
缓存实现代码
/** * 全能型获取图片缓存 (兼容单个链接与链接数组 + 秒开优化) */ export function getImageStorage(url) { return new Promise((resolve) => { // 1. 如果是数组,通过 map 循环调用自身,并用 Promise.all 等待所有结果 if (Array.isArray(url)) { Promise.all(url.map(item => getImageStorage(item))) .then(results => resolve(results)) .catch(() => resolve(url)); // 异常兜底,返回原数组 return; } // 2. 单个链接处理逻辑 if (!url) { resolve(''); return; } // 智能处理 baseUrl 拼接(防止完整的 http/https 链接被重复拼接) // 注意:请确保你的工具文件里已经定义了 baseUrl,如果 url 已经是完整链接则不拼接 const fullUrl = (url.startsWith('http://') || url.startsWith('https://')) ? url : (typeof baseUrl !== 'undefined' ? baseUrl + url : url); // 提取文件名作为缓存 key(兼容带参数的 OSS 链接) const pathWithoutQuery = fullUrl.split('?')[0]; const fullFileName = pathWithoutQuery.substring(pathWithoutQuery.lastIndexOf('/') + 1); const fileNameWithoutExt = fullFileName.substring(0, fullFileName.lastIndexOf('.')) || fullFileName; const storageKey = "IMG_CACHE_" + fileNameWithoutExt; // 本地文件路径缓存 key const urlCacheKey = "URL_CACHE_" + fileNameWithoutExt; // 网络链接兜底缓存 key // --- 核心秒开逻辑:优先读取本地缓存的下载路径 --- const localUrl = uni.getStorageSync(storageKey); if (localUrl) { uni.setStorageSync(urlCacheKey, fullUrl); // 顺便更新一下网络链接缓存 resolve(localUrl); return; } // --- 核心秒开逻辑:如果没有本地文件,看看有没有缓存的网络链接 --- const cachedUrl = uni.getStorageSync(urlCacheKey); if (cachedUrl) { resolve(cachedUrl); // 立刻返回缓存的链接,让页面先渲染出来(实现秒开) } // 3. 执行下载和持久化缓存逻辑 // #ifndef H5 uni.downloadFile({ url: fullUrl, success: (res) => { if (res.statusCode === 200) { const saveSuccess = (savedFilePath) => { uni.setStorageSync(storageKey, savedFilePath); uni.setStorageSync(urlCacheKey, fullUrl); resolve(savedFilePath); }; const saveFail = () => resolve(fullUrl); // 失败兜底返回原链接 // #ifndef MP-WEIXIN || MP-KUAISHOU uni.saveFile({ tempFilePath: res.tempFilePath, success: (r) => saveSuccess(r.savedFilePath), fail: saveFail }); // #endif // #ifdef MP-WEIXIN wx.getFileSystemManager().saveFile({ tempFilePath: res.tempFilePath, success: (r) => saveSuccess(r.savedFilePath), fail: saveFail }); // #endif // #ifdef MP-KUAISHOU ks.saveFile({ tempFilePath: res.tempFilePath, success: (r) => saveSuccess(r.savedFilePath), fail: saveFail }); // #endif } else { resolve(fullUrl); } }, fail: () => resolve(fullUrl), }) // #endif // #ifdef H5 // H5端 fetchBlobDataAsBase64 逻辑(需确保你文件里有这个辅助函数) fetchBlobDataAsBase64(fullUrl) .then(base64Data => { const [header, data] = base64Data.split(','); const mimeType = header.match(/:(.*?);/)[1]; const base64 = `data:${mimeType};base64,${data}`; uni.setStorageSync(storageKey, base64); uni.setStorageSync(urlCacheKey, fullUrl); resolve(base64); }) .catch(() => resolve(fullUrl)) // #endif }); } // H5端辅助函数 function fetchBlobDataAsBase64(blobUrl) { return new Promise((resolve, reject) => { fetch(blobUrl) .then(response => response.blob()) .then(blob => { const reader = new FileReader(); reader.onloadend = () => resolve(reader.result); reader.onerror = () => reject(new Error('无法读取文件')); reader.readAsDataURL(blob); }) .catch(error => reject(error)); }); }使用方法
引入方法--import {getImageStorage} from '../../../util/chatImage.js',根据实际项目写入正确路劲。
在首次获取图片资源的时候调用方法,实现数据缓存this.rulesImageUrl = await getImageStorage(res.data.rulesImageUrl);
