面试题答案
一键面试1. 实现网络请求合并的方法
在Vue项目中,可以借助Promise
和一个请求队列来实现网络请求合并。以下是具体实现步骤:
- 创建请求队列:
使用一个对象来存储相同接口但不同参数的请求,对象的键可以是接口地址,值是一个数组,数组中存放每个请求的参数和对应的
Promise
。
const requestQueue = {};
- 封装请求函数:
import axios from 'axios';
function mergedRequest(url, params) {
if (!requestQueue[url]) {
requestQueue[url] = [];
}
return new Promise((resolve, reject) => {
// 检查队列中是否已有相同参数的请求
const existingRequest = requestQueue[url].find(req => req.params === params);
if (existingRequest) {
existingRequest.promise.then(resolve).catch(reject);
} else {
// 没有则添加到队列
const newRequest = { params, promise: null };
requestQueue[url].push(newRequest);
if (requestQueue[url].length === 1) {
// 只有一个请求时,发起实际请求
axios.get(url, { params })
.then(response => {
requestQueue[url].forEach(req => req.promise.resolve(response));
requestQueue[url] = [];
})
.catch(error => {
requestQueue[url].forEach(req => req.promise.reject(error));
requestQueue[url] = [];
});
}
newRequest.promise = new Promise((innerResolve, innerReject) => {
resolve = innerResolve;
reject = innerReject;
});
}
});
}
- 在Vue组件中使用:
<template>
<div>
<button @click="fetchData">Fetch Data</button>
</div>
</template>
<script>
export default {
methods: {
async fetchData() {
const result1 = await mergedRequest('/api/data', { param1: 'value1' });
const result2 = await mergedRequest('/api/data', { param1: 'value2' });
console.log(result1, result2);
}
}
};
</script>
2. 实现过程中遇到的问题及解决方法
- 问题1:请求队列清理不及时
- 原因:如果请求队列没有及时清理,会导致内存占用过高,特别是在频繁发起请求的场景下。
- 解决方法:在请求成功或失败后,及时清空请求队列。如上述代码中,在
axios
请求的then
和catch
回调中,都将requestQueue[url]
置为空数组。
- 问题2:参数处理复杂
- 原因:当请求参数是复杂对象时,比较参数是否相同会变得复杂,简单的
===
比较无法满足需求。 - 解决方法:可以使用
JSON.stringify
将参数对象转换为字符串进行比较,但要注意对象属性顺序可能影响结果。也可以使用更复杂的深度比较算法,如lodash
的isEqual
方法。
- 原因:当请求参数是复杂对象时,比较参数是否相同会变得复杂,简单的
- 问题3:请求并发控制
- 原因:如果同一时间有大量相同接口不同参数的请求进入队列,一次性发起可能会对服务器造成压力。
- 解决方法:可以设置一个并发数限制,比如同一时间只允许发起一定数量的相同接口请求。可以使用
Promise.allSettled
结合队列分批处理请求。例如,将请求队列按并发数分组,依次处理每组请求。
function batchRequest(url, requests, concurrency) {
const batches = [];
for (let i = 0; i < requests.length; i += concurrency) {
batches.push(requests.slice(i, i + concurrency));
}
return Promise.all(batches.map(batch => {
const batchPromises = batch.map(req => axios.get(url, { params: req.params }));
return Promise.allSettled(batchPromises);
}));
}
在上述mergedRequest
函数中,当需要发起实际请求时,调用batchRequest
函数来控制并发。