File size: 4,966 Bytes
9e40388 3b9298b 9e40388 3b9298b 9e40388 3b9298b 9e40388 3b9298b 9e40388 3b9298b 9e40388 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
import { urlCacheManager } from './urlCache.js'
// 请求去重映射
const pendingRequests = new Map()
/**
* 带缓存的音乐图片URL获取函数
* @param {string} source - 音乐源
* @param {string} id - 图片ID
* @param {string|number} size - 图片尺寸
* @param {boolean} skipCache - 是否跳过缓存
* @returns {Promise<string>} 图片URL
*/
export async function getCachedMusicPicUrl(source, id, size = 300, skipCache = false) {
if (!source || !id) return null
// 强制使用 300 尺寸,不管传入什么参数
const sizeStr = '300'
// 先检查缓存(除非明确跳过)
if (!skipCache) {
const cached = urlCacheManager.getCachedUrl(source, id, sizeStr)
if (cached) {
return cached
}
}
// 检查是否有正在进行的相同请求(去重)
const requestKey = `${source}+${id}+${sizeStr}`
if (pendingRequests.has(requestKey)) {
return pendingRequests.get(requestKey)
}
// 创建新的API请求
const apiUrl = `https://music-api.gdstudio.xyz/api.php?types=pic&source=${encodeURIComponent(source)}&id=${encodeURIComponent(id)}&size=${encodeURIComponent(sizeStr)}`
const requestPromise = fetch(apiUrl)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
return response.json()
})
.then(data => {
let resultUrl = null
if (data && data.url) {
resultUrl = data.url
// 将结果存入缓存
urlCacheManager.setCachedUrl(source, id, sizeStr, resultUrl)
}
return resultUrl
})
.catch(error => {
console.error('获取音乐图片失败:', error)
return null
})
.finally(() => {
// 请求完成后从去重映射中移除
pendingRequests.delete(requestKey)
})
// 将请求添加到去重映射
pendingRequests.set(requestKey, requestPromise)
return requestPromise
}
/**
* 带延时的音乐图片URL获取函数(懒加载专用)
* 第一个请求立即执行,后续请求间隔200ms
* @param {string} source - 音乐源
* @param {string} id - 图片ID
* @param {string|number} size - 图片尺寸
* @returns {Promise<string>} 图片URL
*/
export async function getCachedMusicPicUrlWithDelay(source, id, size = 300) {
if (!source || !id) return null
// 强制使用 300 尺寸,不管传入什么参数
const sizeStr = '300'
// 先检查缓存
const cached = urlCacheManager.getCachedUrl(source, id, sizeStr)
if (cached) {
// 缓存命中,直接返回,无需延时
return cached
}
// 缓存未命中,需要请求API
// 如果不是第一个请求,添加200ms延时
const requestKey = `${source}+${id}+${sizeStr}`
if (pendingRequests.size > 0) {
await new Promise(resolve => setTimeout(resolve, 200))
}
return getCachedMusicPicUrl(source, id, 300)
}
/**
* 批量预加载音乐图片URL
* @param {Array} songs - 歌曲数组,每个歌曲应包含source和pic_id字段
* @param {string|number} size - 图片尺寸
* @param {number} concurrency - 并发数量
*/
export async function preloadMusicPics(songs, size = 300, concurrency = 1) {
if (!Array.isArray(songs) || songs.length === 0) return
// 强制使用 300 尺寸,不管传入什么参数
const sizeStr = '300'
// 过滤出需要加载的歌曲(未缓存的)
const toLoad = songs.filter(song => {
if (!song.source || !song.pic_id) return false
return !urlCacheManager.getCachedUrl(song.source, song.pic_id, sizeStr)
})
if (toLoad.length === 0) return
// 分批并发加载
for (let i = 0; i < toLoad.length; i += concurrency) {
const batch = toLoad.slice(i, i + concurrency)
const promises = batch.map(song =>
getCachedMusicPicUrl(song.source, song.pic_id, 300).catch(error => {
console.warn(`预加载 ${song.name} 图片失败:`, error)
return null
})
)
await Promise.all(promises)
// 批次间间隔200ms
if (i + concurrency < toLoad.length) {
await new Promise(resolve => setTimeout(resolve, 200))
}
}
}
/**
* 清除指定歌曲的图片缓存
* @param {string} source - 音乐源
* @param {string} id - 图片ID
*/
export function clearMusicPicCache(source, id) {
if (!source || !id) return
// 清除所有尺寸的缓存
const commonSizes = ['300', '500', '800', '1200']
commonSizes.forEach(size => {
const key = urlCacheManager.getCacheKey(source, id, size)
urlCacheManager.cache.delete(key)
})
urlCacheManager.saveToStorage()
}
/**
* 获取缓存统计信息
*/
export function getCacheStats() {
return urlCacheManager.getStats()
}
/**
* 清空所有缓存
*/
export function clearAllCache() {
urlCacheManager.clear()
}
export default {
getCachedMusicPicUrl,
getCachedMusicPicUrlWithDelay,
preloadMusicPics,
clearMusicPicCache,
getCacheStats,
clearAllCache
} |