MST

星途 面试题库

面试题:TypeScript 异步函数剩余参数在复杂场景下的应用与性能优化

假设你正在开发一个资源加载器,有一个异步函数 `loadResources`,它接受任意数量的资源路径作为剩余参数。这些资源可能是图片、脚本或者其他文件。要求按照资源类型(通过路径后缀判断)进行分组加载,例如图片一起加载,脚本一起加载等,并且不同类型资源的加载并发数是不同的(假设图片并发数为 3,脚本并发数为 5 等)。加载完成后返回一个对象,对象的键为资源类型,值为该类型下所有成功加载的资源内容(可以简单用字符串模拟资源内容)。请用 TypeScript 实现该函数,并对性能优化方面进行说明。
22.7万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试
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;
}

性能优化说明

  1. 分组加载:通过 getResourceType 函数将资源按类型分组,不同类型资源并行加载,减少总体加载时间。
  2. 控制并发数:为每种资源类型设置并发数,避免过多并发请求造成资源浪费或网络阻塞。通过 Promise.race 来管理并发,确保并发数不超过设定值。
  3. 缓存机制:如果可能,添加缓存机制,对于相同路径的资源,直接从缓存中获取,减少重复加载。
  4. 错误处理:在实际应用中,load 函数中应该添加错误处理,对于加载失败的资源进行重试或者记录错误日志,避免因为某个资源加载失败而导致整个加载过程中断。