目录
背景
最近小伙伴去面试,被问到了这个问题,我打眼一看这是个伪命题啊!有100个请求发送,这是产品经理把功能揉在了一个页面上还是后端有上万张数据表啊,整这么复杂。但后来细品,这的确是一个有价值的问题,能考虑的点绝对不是前端优化这么简单。
实际会出现吗
一般情况下硬编码的情况不会。在设计功能时有经验的产品经理一般非常注重功能解耦的,否则以后添加需求自己也难以设计,产品生命周期估计无法达到100个接口并发的迭代。后端不愿意也不会出太多的接口,最多列表页接口加ids查询就了不起了,再加多对服务器端压力也是挑战。
但总有特殊场景会出现,以我们公司的低代码自定义首页为例,首页可以通过拖动若干个业务组件配置实现,组件上限100个,若每个业务组件平均有1个查询接口,我配置100个组件也能基本满足题目需要了,更何况还不算一些配置的获取。
天下之大无奇不有,这种需求从业务设计而言不易避免,随着日益增长的web端需求复杂度,再离谱的情况都有可能。
以我们公司产品的首页举例,配置了16个组件,再加上一些其他接口,如国际化、各个业务配置、特殊信息获取等,这已经达到58个接口了(已经是三个版本优化后的情况)。
完成所有的请求花了3.47s,当然根据时序图可以看到这里其实做了懒加载并且网络环境良好的情况下。不过我们仍然可以得出结论,在这段时间内切换组件或页面是有绝对可操作行为的,因此在实际的场景中,真的是能够实现的,并且问题是有意义有价值的。
该怎么优化
根据面试官的描述,我们需要明白要优化是为了达到什么效果,解决什么问题,以终为始,思路就会更加清晰。比如是因为接口调用过多导致了服务器压力大,还是因为用户体验不好流畅度不高,还是突然切页面的操作导致某些请求未完成业务不完整。
根据以上的分析,我们可以考虑两个方向。一是如何在优化请求下功夫;二是如何在页面交互下功夫。
优化请求
我们知道,浏览器对每个域名的请求并发限制是6个,超过的部分会排队,等待前边的请求响应后方可执行,axios在create时往往会配置超时时长,服务器也可能添加超时策略,也会影响我们请求的执行过程。
- 使用Promise.all(),Promise.race()或者Promise.allSettled(),酌情对异步进行控制,从而更好管理异步任务和优化调用顺序。
- 使用组件、图片懒加载,保证优先请求和渲染视口中的元素,减少请求压力,提高用户体验。
- 引入缓存机制,如弱实时性、低交互频率或静态数据等接口,可以考虑使用缓存,减少请求次数。
- 升级HTTP2.0/3.0,利用传输层的底层优化来提高请求效率,当然,也需要根据实际背景以及考虑兼容性等情况。
- 使用webSocket,在实时性要求较高的业务中,可以考虑使用websocket长链接,减少HTTP请求的同时,也提高了数据的实时性。
- 使用webWorker,站在浏览器的角度创建JS的多线程环境,为主线程分忧,但同样要考虑兼容性。
- 合并请求,梳理接口逻辑,将接口合并或聚合,从真实接口数量层面优化。
优化交互
根据描述,在接口请求未完成时切换页面,那么问题就变成了切换页面时,这些未完成的接口如何处理。
如何知道接口有没有完成
可定义一个请求队列,可存到vuex、pinia等状态管理中,用来管理请求状态,每个请求可以使用id进行标识以便区分(uuid、nano标识也可以),接口请求时入队,请求完成出队,用此队列管理和记录接口的状态,以下是部分伪代码。
// 定义一个请求队列
const axiosQueue = [];
// 将axios实例加入请求队列
const enQueue = (id, axiosInstance) => {
axiosQueue.push({
id,
axiosInstance
});
};
// 出队
const deQueue = () => {
axiosQueue.shift();
};
// 批量出队
const deQueueMuti = (ids) => {
const idsArr = ids.split(',');
axiosQueue.filter(item => idsArr.includes(item.id));
};
// 执行请求队列
const runQueue = () => {
axiosQueue.forEach(item => {
doAxios(item.axiosInstance);
});
};
未完成的接口该如何处理
对请求提前分类,如上报数据类(关系业务正确性和数据完整性,需要补充请求)、查询数据类(组件销毁后,再查询没有意义,不需要补充请求)。
当切换页面时(组件销毁前),应立即阻断所有还在队列中的请求,如使用axios的cancelToken进行请求的取消操作。在新页面初始化时,查询队列,判断队列中的请求不需要的过滤掉,需要的在新页面进行补充请求。
扩展与总结
除了接口合并等优化方案需要后端主导,前端能做的其实不止这些,像限流、请求控制等。但同样是解决问题,更多与产品经理沟通,更多与后端合作分析也有利于获取信息和开拓思路,明白了需求和产品定位之后,或许能有新的发现。