1
This commit is contained in:
390
utils/performance.js
Normal file
390
utils/performance.js
Normal file
@@ -0,0 +1,390 @@
|
||||
/**
|
||||
* 性能优化工具集
|
||||
* 包含防抖、节流、懒加载、缓存等功能
|
||||
*/
|
||||
|
||||
/**
|
||||
* 防抖函数
|
||||
* @param {Function} func 要执行的函数
|
||||
* @param {Number} wait 延迟时间(毫秒)
|
||||
* @param {Boolean} immediate 是否立即执行
|
||||
*/
|
||||
function debounce(func, wait = 300, immediate = false) {
|
||||
let timeout
|
||||
|
||||
return function executedFunction(...args) {
|
||||
const context = this
|
||||
|
||||
const later = function() {
|
||||
timeout = null
|
||||
if (!immediate) func.apply(context, args)
|
||||
}
|
||||
|
||||
const callNow = immediate && !timeout
|
||||
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(later, wait)
|
||||
|
||||
if (callNow) func.apply(context, args)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 节流函数
|
||||
* @param {Function} func 要执行的函数
|
||||
* @param {Number} limit 时间限制(毫秒)
|
||||
*/
|
||||
function throttle(func, limit = 300) {
|
||||
let inThrottle
|
||||
|
||||
return function(...args) {
|
||||
const context = this
|
||||
|
||||
if (!inThrottle) {
|
||||
func.apply(context, args)
|
||||
inThrottle = true
|
||||
setTimeout(() => inThrottle = false, limit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存管理器
|
||||
*/
|
||||
class CacheManager {
|
||||
constructor() {
|
||||
this.cache = new Map()
|
||||
this.maxSize = 50 // 最大缓存数量
|
||||
this.ttl = 5 * 60 * 1000 // 默认5分钟过期
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置缓存
|
||||
*/
|
||||
set(key, value, ttl = this.ttl) {
|
||||
if (this.cache.size >= this.maxSize) {
|
||||
// 删除最早的缓存
|
||||
const firstKey = this.cache.keys().next().value
|
||||
this.cache.delete(firstKey)
|
||||
}
|
||||
|
||||
this.cache.set(key, {
|
||||
value,
|
||||
expires: Date.now() + ttl
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存
|
||||
*/
|
||||
get(key) {
|
||||
const item = this.cache.get(key)
|
||||
|
||||
if (!item) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (Date.now() > item.expires) {
|
||||
this.cache.delete(key)
|
||||
return null
|
||||
}
|
||||
|
||||
return item.value
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
*/
|
||||
delete(key) {
|
||||
return this.cache.delete(key)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空缓存
|
||||
*/
|
||||
clear() {
|
||||
this.cache.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存大小
|
||||
*/
|
||||
size() {
|
||||
return this.cache.size
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理过期缓存
|
||||
*/
|
||||
cleanup() {
|
||||
const now = Date.now()
|
||||
for (const [key, item] of this.cache.entries()) {
|
||||
if (now > item.expires) {
|
||||
this.cache.delete(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片懒加载管理器
|
||||
*/
|
||||
class LazyLoadManager {
|
||||
constructor() {
|
||||
this.observer = null
|
||||
this.images = []
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化懒加载
|
||||
*/
|
||||
init(selector = '.lazy-image') {
|
||||
if (!wx.createIntersectionObserver) {
|
||||
console.warn('当前环境不支持IntersectionObserver')
|
||||
return
|
||||
}
|
||||
|
||||
this.observer = wx.createIntersectionObserver()
|
||||
|
||||
this.observer.relativeToViewport({ bottom: 100 })
|
||||
|
||||
this.observer.observe(selector, (res) => {
|
||||
if (res.intersectionRatio > 0) {
|
||||
this.loadImage(res.id)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载图片
|
||||
*/
|
||||
loadImage(id) {
|
||||
const image = this.images.find(img => img.id === id)
|
||||
if (image && !image.loaded) {
|
||||
image.loaded = true
|
||||
// 触发图片加载
|
||||
if (image.callback) {
|
||||
image.callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加图片
|
||||
*/
|
||||
addImage(id, callback) {
|
||||
this.images.push({ id, loaded: false, callback })
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁
|
||||
*/
|
||||
destroy() {
|
||||
if (this.observer) {
|
||||
this.observer.disconnect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页加载管理器
|
||||
*/
|
||||
class PaginationManager {
|
||||
constructor(config = {}) {
|
||||
this.pageSize = config.pageSize || 20
|
||||
this.currentPage = 1
|
||||
this.totalPages = 0
|
||||
this.totalCount = 0
|
||||
this.hasMore = true
|
||||
this.loading = false
|
||||
this.data = []
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载下一页
|
||||
*/
|
||||
async loadMore(fetchFunction) {
|
||||
if (this.loading || !this.hasMore) {
|
||||
return null
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
|
||||
try {
|
||||
const result = await fetchFunction(this.currentPage, this.pageSize)
|
||||
|
||||
this.data = [...this.data, ...result.data]
|
||||
this.totalCount = result.total
|
||||
this.totalPages = Math.ceil(result.total / this.pageSize)
|
||||
this.hasMore = this.currentPage < this.totalPages
|
||||
this.currentPage++
|
||||
|
||||
return result
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置
|
||||
*/
|
||||
reset() {
|
||||
this.currentPage = 1
|
||||
this.totalPages = 0
|
||||
this.totalCount = 0
|
||||
this.hasMore = true
|
||||
this.loading = false
|
||||
this.data = []
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态
|
||||
*/
|
||||
getState() {
|
||||
return {
|
||||
currentPage: this.currentPage,
|
||||
totalPages: this.totalPages,
|
||||
totalCount: this.totalCount,
|
||||
hasMore: this.hasMore,
|
||||
loading: this.loading,
|
||||
dataLength: this.data.length
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 性能监控器
|
||||
*/
|
||||
class PerformanceMonitor {
|
||||
constructor() {
|
||||
this.metrics = []
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始监控
|
||||
*/
|
||||
start(name) {
|
||||
return {
|
||||
name,
|
||||
startTime: Date.now(),
|
||||
end: () => this.end(name, Date.now())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束监控
|
||||
*/
|
||||
end(name, startTime) {
|
||||
const duration = Date.now() - startTime
|
||||
|
||||
this.metrics.push({
|
||||
name,
|
||||
duration,
|
||||
timestamp: Date.now()
|
||||
})
|
||||
|
||||
// 性能警告
|
||||
if (duration > 1000) {
|
||||
console.warn(`[性能警告] ${name} 耗时 ${duration}ms`)
|
||||
}
|
||||
|
||||
return duration
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指标
|
||||
*/
|
||||
getMetrics(name) {
|
||||
if (name) {
|
||||
return this.metrics.filter(m => m.name === name)
|
||||
}
|
||||
return this.metrics
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取平均时间
|
||||
*/
|
||||
getAverage(name) {
|
||||
const metrics = this.getMetrics(name)
|
||||
if (metrics.length === 0) return 0
|
||||
|
||||
const total = metrics.reduce((sum, m) => sum + m.duration, 0)
|
||||
return total / metrics.length
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空指标
|
||||
*/
|
||||
clear() {
|
||||
this.metrics = []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据预加载管理器
|
||||
*/
|
||||
class PreloadManager {
|
||||
constructor() {
|
||||
this.preloadQueue = []
|
||||
this.maxConcurrent = 3
|
||||
this.running = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加预加载任务
|
||||
*/
|
||||
add(task, priority = 0) {
|
||||
this.preloadQueue.push({ task, priority })
|
||||
this.preloadQueue.sort((a, b) => b.priority - a.priority)
|
||||
this.process()
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理队列
|
||||
*/
|
||||
async process() {
|
||||
while (this.running < this.maxConcurrent && this.preloadQueue.length > 0) {
|
||||
const { task } = this.preloadQueue.shift()
|
||||
this.running++
|
||||
|
||||
try {
|
||||
await task()
|
||||
} catch (e) {
|
||||
console.error('预加载失败:', e)
|
||||
} finally {
|
||||
this.running--
|
||||
this.process()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空队列
|
||||
*/
|
||||
clear() {
|
||||
this.preloadQueue = []
|
||||
}
|
||||
}
|
||||
|
||||
// 创建全局实例
|
||||
const cacheManager = new CacheManager()
|
||||
const performanceMonitor = new PerformanceMonitor()
|
||||
const preloadManager = new PreloadManager()
|
||||
|
||||
// 定期清理过期缓存
|
||||
setInterval(() => {
|
||||
cacheManager.cleanup()
|
||||
}, 60 * 1000) // 每分钟清理一次
|
||||
|
||||
module.exports = {
|
||||
debounce,
|
||||
throttle,
|
||||
CacheManager,
|
||||
cacheManager,
|
||||
LazyLoadManager,
|
||||
PaginationManager,
|
||||
PerformanceMonitor,
|
||||
performanceMonitor,
|
||||
PreloadManager,
|
||||
preloadManager
|
||||
}
|
||||
Reference in New Issue
Block a user