type ResourceType = 'image' |'script' | 'other';
interface ResourceLoader {
type: ResourceType;
concurrency: number;
load: (path: string) => Promise<string>;
}
const resourceLoaders: { [key in ResourceType]: ResourceLoader } = {
image: {
type: 'image',
concurrency: 3,
load: (path) => {
// 模拟图片加载
return Promise.resolve(`Image content from ${path}`);
}
},
script: {
type:'script',
concurrency: 5,
load: (path) => {
// 模拟脚本加载
return Promise.resolve(`Script content from ${path}`);
}
},
other: {
type: 'other',
concurrency: 1,
load: (path) => {
// 模拟其他文件加载
return Promise.resolve(`Other content from ${path}`);
}
}
};
function getResourceType(path: string): ResourceType {
const ext = path.split('.').pop()?.toLowerCase();
if (['jpg', 'png', 'jpeg', 'gif'].includes(ext || '')) {
return 'image';
} else if (['js'].includes(ext || '')) {
return'script';
}
return 'other';
}
async function loadResources(...paths: string[]): Promise<{ [key in ResourceType]: string[] }> {
const typeGroups: { [key in ResourceType]: string[] } = {
image: [],
script: [],
other: []
};
for (const path of paths) {
const type = getResourceType(path);
typeGroups[type].push(path);
}
const result: { [key in ResourceType]: string[] } = {
image: [],
script: [],
other: []
};
for (const type in typeGroups) {
const loader = resourceLoaders[type as ResourceType];
const paths = typeGroups[type as ResourceType];
const promises: Promise<string>[] = [];
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
if (promises.length >= loader.concurrency) {
const completed = await Promise.race(promises);
result[type as ResourceType].push(completed);
promises.splice(promises.indexOf(completed), 1);
}
promises.push(loader.load(path));
}
const remaining = await Promise.all(promises);
result[type as ResourceType].push(...remaining);
}
return result;
}
性能优化说明
- 分组加载:通过
getResourceType
函数将资源按类型分组,不同类型资源并行加载,减少总体加载时间。
- 控制并发数:为每种资源类型设置并发数,避免过多并发请求造成资源浪费或网络阻塞。通过
Promise.race
来管理并发,确保并发数不超过设定值。
- 缓存机制:如果可能,添加缓存机制,对于相同路径的资源,直接从缓存中获取,减少重复加载。
- 错误处理:在实际应用中,
load
函数中应该添加错误处理,对于加载失败的资源进行重试或者记录错误日志,避免因为某个资源加载失败而导致整个加载过程中断。