Files
miniprogram-1/miniprogram/components/cloud-image/cloud-image.ts
2026-01-13 20:50:02 +08:00

99 lines
2.2 KiB
TypeScript

import apiManager from '../../utils/api';
// Global memory cache for image URLs
const urlCache = new Map<string, string>();
// Track pending requests to avoid duplicate fetches for the same fileId
const pendingRequests = new Map<string, Promise<string>>();
Component({
virtualHost: true,
properties: {
fileId: {
type: String,
observer: 'loadUrl'
},
width: {
type: String,
value: '100%'
},
height: {
type: String,
value: '100%'
},
mode: {
type: String,
value: 'widthFix'
},
radius: {
type: String,
value: '0'
}
},
data: {
imageUrl: '',
isLoading: true,
isError: false
},
methods: {
async loadUrl(this: any, fileId: string) {
if (!fileId) {
this.setData({ imageUrl: '', isLoading: false });
return;
}
// Check cache first
if (urlCache.has(fileId)) {
this.setData({
imageUrl: urlCache.get(fileId),
isLoading: false,
isError: false
});
return;
}
this.setData({ isLoading: true, isError: false });
try {
let promise = pendingRequests.get(fileId);
if (!promise) {
promise = apiManager.getFileDisplayUrl(fileId);
pendingRequests.set(fileId, promise);
}
const url = await promise;
urlCache.set(fileId, url);
pendingRequests.delete(fileId);
// Ensure the fileId hasn't changed while we were fetching
if (this.data.fileId === fileId) {
console.log('[CloudImage] Loaded url for', fileId, url)
this.setData({
imageUrl: url,
isLoading: false
});
}
} catch (e) {
console.error('Failed to load image url for fileId:', fileId, e);
if (this.data.fileId === fileId) {
this.setData({
isLoading: false,
isError: true
});
}
pendingRequests.delete(fileId);
}
},
onLoad(this: any, e: any) {
this.triggerEvent('load', e);
},
onError(this: any, e: any) {
this.setData({ isError: true, isLoading: false });
this.triggerEvent('error', e);
}
}
});